zoukankan      html  css  js  c++  java
  • [题解] [CF451E] Devu and Flowers

    题面

    题解

    就是一个求(sum_{i= 1}^{n}x _ i = m)的不重复多重集的个数, 我们可以由容斥原理得到:

    [ans = C_{n + m - 1}^{n - 1} - sum_{i = 1}^{n}C_{n + m - f_i - 2}^{n - 1} + sum_{1 leq i < j leq n}C_{n + m - f_i - f_j - 3}^{n - 1} - cdots + (-1)^n C_{n + m - sum_{k = 1}^{n}f_k -(n + 1)}^{n - 1} ]

    数据范围中(1leq Nleq 20)告诉了我们什么?

    我们考虑枚举(x = 0 sim 2 ^ n - 1), 设(x)在二进制表示下共有(p)位为1, 分别是(i_1, i_2, i_3, cdots, i_p), 则这个(x)对答案的贡献就是

    [(-1)^pC_{n+m-sum_{k=1}^{p}f_{i_k}-(p+1)}^{n-1} ]

    注意到(x)为0时它对答案的贡献为(C_{n + m - 1}^{n - 1})

    还是因为(N)比较小, 我们可以将(C_{n+m-1}^{n-1})转化为(P_{n+m-1}^{n-1}/(n-1)!)

    由于(P_{n+m-1}^{n-1}=(n+m-1)*(n+m-2)*cdots*((n+m-1)-(n-1)+1)), 再乘上一个((n-1)!)的逆元就可以算出来了, 最后对于每个(x)求个和即可

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #define itn int
    #define reaD read
    #define mod 1000000007
    #define int long long
    using namespace std;
    
    int n, m, f[22], inv[22], ans; 
    
    inline int read()
    {
    	int x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    	return x * w;
    }
    
    int fpow(int x, int y)
    {
    	int res = 1;
    	while(y)
    	{
    		if(y & 1) res = res * x % mod;
    		x = x * x % mod;
    		y >>= 1; 
    	}
    	return res; 
    }
    
    int lucas(int n, int m)
    {
    	if(n < 0 || m < 0 || n < m) return 0;
    	n %= mod;
    	if(!n || !m) return 1;
    	int res = 1;
    	for(int i = n; i >= n - m + 1; i--) res = res * i % mod;
    	res = res * inv[m] % mod;
    	return res; 
    }
    
    signed main()
    {
    	n = read(); m = read(); inv[0] = 1;
    	for(int i = 1; i <= n; i++) f[i] = reaD();
    	for(int i = 1; i <= 20; i++) inv[i] = fpow(i, mod - 2);
    	for(int i = 1; i <= 20; i++) inv[i] = inv[i] * inv[i - 1] % mod;
    	for(int x = 0; x < (1 << n); x++)
    	{
    		if(!x) { ans = (ans + lucas(n + m - 1, n - 1)) % mod; continue; }
    		int num = n + m - 1, cnt = 0;
    		for(int i = 0; i < n; i++) if((x >> i) & 1) cnt++, num -= f[i + 1] + 1;
    		if(cnt % 2) ans = ((ans - lucas(num, n - 1)) % mod + mod) % mod;
    		else ans = (ans + lucas(num, n - 1)) % mod; 
    	}
    	printf("%lld
    ", ans); 
    	return 0;
    }
    
  • 相关阅读:
    javascript设计思维
    asp.net时间类-格式-方法应用
    javascript简写精练
    保存html代码
    jQuery.cookie应用操作
    ASP.NET 打包多CSS或JS文件以加快页面加载速度的Handler
    Asp.Net下通过切换CSS换皮肤
    让你的ASP.NET虚拟主机也支持子网站
    javascript获取和设置URL中的参数
    获取和设置URL里星号(#)的参数
  • 原文地址:https://www.cnblogs.com/ztlztl/p/11094190.html
Copyright © 2011-2022 走看看