题目:
化式子到 ( \mul_{i=1}^{n}(1-x^(m[i]+1)) ) / (1-x)^n 之后就不会了。
其实把分子拿出来后的部分可以展开成一个式子,用组合意义可知 k 次项系数是 C( n-1+k,n-1 ) 。
分子的那部分可以暴搜 2^n 种可能的项!一个项 k * x^y 对答案的贡献就是 k*( \sum_{i=L-y}^{R-y}C(n-1+i,n-1) );考虑完这 2^n 种情况对答案的贡献后答案就算好了。
组合数一列的求和可以是那个右下角位置的值。
模数可能让组合数不能除,但可以把要除的 n! 乘进模数里,即 % (mod*n!) ,最后就可以把答案除以 n! 再输出了。
注意负数。
#include#include #include #include #define ll long longusing namespace std;const int N=15,M=1030;int n,m,w[N],L,R;ll mod,ans;void upd(ll &x){x>=mod?x-=mod:0;}ll calc(int k){ ll ret=1; for(int i=k+1;i<=k+n;i++) ret=ret*i%mod; return ret;}void dfs(int cr,int xs,int cs){ if(cs>R)return; if(cr>n) { ll d=calc(R-cs)+mod-(L-cs-1<0?0:calc(L-cs-1)); upd(d); ans=(ans+xs*d)%mod;//xs may <0 so ans may <0!!! return; } dfs(cr+1,xs,cs); dfs(cr+1,-xs,cs+w[cr]+1);}int main(){ scanf("%d%d%d",&n,&L,&R); for(int i=1;i<=n;i++)scanf("%d",&w[i]); m=1;for(int i=1;i<=n;i++)m*=i; mod=(ll)2004*m; dfs(1,1,0); if(ans<0)ans+=mod;/// printf("%lld\n",ans/m); return 0;}