codeforces 451E Devu and Flowers (指数型母函数)

http://codeforces.com/problemset/problem/451/E 题意;有n个花坛,要选s支花,每个花坛有f[i]支花,同一个花坛的花颜色相同,不同花坛的花颜色不同,问说可以有多少种组合。 思路:典型的母函数...然而s有点大,根据泰勒展开什么的...先转一下官方题解。

The number of ways to choose _N_ items out of _R_ groups where each item in a group is identical is equal to the number of integral solutions to _x_1 + _x_2 + _x_3..._x__R_ = _N_, where 0 ≤ _x__i_ ≤ _L__i_, where _L__i_ is the number of items in _i__th_ group. Number of integral solutions are coefficient of _x__N_ in [Product of (1 + _x_ + _x_ * _x_ + ..._x__L__i_) over all $i$].

You need to find coefficient of x__s in (1 + x + _x_2 + _x_3 +  + .._x__f_1) *  *  * (1 + x + _x_2 + _x_3 +  + ..x__f__n).

Using sum of Geometric progression we can say that(1 + x + _x_2 + _x_3 +  + .._x__f_1) = (1 - x(_f_1 + 1)) / (1 - x).

Substituting in the expression, we get (1 - x(_f_1 + 1)) / (1 - x) *  *  * (1 - x(f__n + 1)) / (1 - x).

= (1 - x(_f_1 + 1)) * .. * (1 - x(f__n + 1)) * (1 - x)( - n).

Now we can find x__s in (1 - x) - n easily. It is .

You can have a look at following link. to understand it better.

So now as s is large, we can not afford to iterate over s.

But n is small, we notice that (1 - x(f_1 + 1)) * .. * (1 - x(f__n + 1)) can have at most 2_n terms.

So we will simply find all those terms, they can be very easily computed by maintaining a vector<pair<int, int> > containing pairs of coefficients and their corresponding powers. You can write a recursive function for doing this.

How to find % p. As n + s - 1 is large and s is very small. You can use lucas's theorem. If you understand lucas's theorem, you can note that we simply have to compute .

Complexity: O(n * 2_n_).

嗯。。。

我推到了这步:(1 - x(_f_1 + 1)) * .. * (1 - x(f__n + 1)) * (1 - x)( - n).

然后不知所措了。

一个不会的点是,一般意义的二项式定理不会,也就是指数为负数的。

然后后面那一串,由于n才20.所以直接暴力展开多项式我是能想到的。。。但是依然不知道怎么写。还有递归的求解方法。。。没有特别明白。

此外需要lucas定理求大组合数,以及预处理一个逆元(代码中的ny数组存的不仅仅是逆元)

/* ***********************************************
Author :111qqz
Created Time :2016年03月02日 星期三 20时54分07秒
File Name :code/cf/problem/451E.cpp
************************************************ */
 1#include <cstdio>
 2#include <cstring>
 3#include <iostream>
 4#include <algorithm>
 5#include <vector>
 6#include <queue>
 7#include <set>
 8#include <map>
 9#include <string>
10#include <cmath>
11#include <cstdlib>
12#include <ctime>
13#define fst first
14#define sec second
15#define lson l,m,rt<<1
16#define rson m+1,r,rt<<1|1
17#define ms(a,x) memset(a,x,sizeof(a))
18typedef long long LL;
19#define pi pair < int ,int >
20#define MP make_pair
1using namespace std;
2const double eps = 1E-8;
3const int dx4[4]={1,0,0,-1};
4const int dy4[4]={0,-1,1,0};
5const int inf = 0x3f3f3f3f;
6const LL mod = 1E9+7;
7int n;
8LL s;
9LL f[35];
 1int ny[35];
 2LL ksm(LL a,LL b)   //快速幂
 3{
 4    LL res = 1;
 5    while (b)
 6    {
 7	if (b&1) res = (res*a)%mod;
 8	b>>=1;
 9	a = (a*a)%mod;
10    }
11    return res;
12}
1void gny()  //ny数组存的不仅仅是逆元...
2{
3    LL val=1  ;
4    for ( LL i = 1 ; i <= 20 ; i++) val = val*i%mod;
5    ny[20]=ksm(val,mod-2);
6    for ( LL i = 19 ; i+1 ; i--) ny[i]=(ny[i+1]*(i+1))%mod;
7}
 1LL cal( LL x,LL y)   //lucas 定理求组合数
 2{
 3    LL res  = 1LL;
 4    for (LL  i = x ; i > x-y ;  i--)  res = (res*(i%mod))%mod;
 5    res = (res*ny[y])%mod;
 6    return res;
 7}
 8LL  solve(LL x,LL s)
 9{
10    if (s<0) return 0;
11    if (x==n+1) return cal(s+n-1,n-1);
12    return (solve(x+1,s)-solve(x+1,s-f[x]-1)+mod)%mod;
13}
14int main()
15{
16	#ifndef  ONLINE_JUDGE 
17	freopen("code/in.txt","r",stdin);
18  #endif
1	ios::sync_with_stdio(false);
2	gny();
3	cin>>n>>s;
4	for ( int i = 1 ; i <= n ; i++)
5	{
6	    cin>>f[i];
7	}
	LL ans = solve(1,s)%mod;
	

	cout<<ans<<endl;
1  #ifndef ONLINE_JUDGE  
2  fclose(stdin);
3  #endif
4    return 0;
5}