您的位置:首页 > 其它

bzoj 3027: [Ceoi2004]Sweet

2017-05-26 08:10 357 查看

一道题含了好多知识点。。

首先母函数不多说看式子。

π(1+x+x^1+x^2+...+x^mi)=π{[1-x^(mi+1)]/[1-x]}=(1-x)^(-n)  *  π(1-x^(mi+1))=(1+x+x^2+...+x^inf..)^n * π(1-x^(mi+1));

然后答案是f(b)-f(a-1) ,f(m) 表示0到m的系数和

那么后面的π(1-x^(mi+1))可以暴力拆出来,最多2^n项,

然后枚举每一项,枚举到 ax^b, 这项 对f(m)的贡献就是(1+x+x^2+...+x^inf..)^n 的 0~m-b的系数和

即,C(0+n-1,n-1)+C(n,n-1)+C(n+1,n-1)+...+C(m-b+n-1,n-1),

  然后因为C(i,i)+C(i+1,i)+...+C(k,i)=C(k+1,i+1);(杨辉三角) 那么上式就可以直接化成一个组合数

C(x,y)%2004 怎么求?

其实问题在于,给定x,y ,x是y的倍数,x很大,y比较小。求(x/y)%p (p也挺小的,但不一定和y互质)

  设z=x/y   ; 求出k=x%(py)  → x=k+tpy;  因为y整除x,so  y整除k,  且我们求出来的k是%py下的 ,gcd(py,y)==y; 所以最后%意义下的k依然是被y整除的。

k/y%p就是最后的 (x/y)%p

 

#include <bits/stdc++.h>
using namespace std;
const int mo=2004;
int n,m,L,R,k,t,w[15];
struct term{
int a,b;
}a[2000],b[2000];
bool cmp(term a,term b){ return a.b<b.b; }
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
int C(int x,int y){
if (x<y) return 0; int z=1,d,u;
for (int i=2;i<=n;++i) w[i]=i;
for (int i=x-y+1;i<=x;++i){       //我用的不是上面那种求法
u=i;
for (int j=2;j<=n;++j) if (w[j]>1) d=gcd(u,w[j]),u/=d,w[j]/=d;
(z*=u%mo)%=mo;
}
return z;
}
int get(int m){
int ans=0;
for (int i=1;i<=t;++i){
ans+=C(m-a[i].b+n,n)*a[i].a%mo;
if (ans>=mo) ans-=mo;
}
return ans;
}
int main(){
scanf("%d%d%d",&n,&L,&R); a[t=1]={1,0}; b[0].b=-1;
for (int i=1;i<=n;++i){
scanf("%d",&m); k=0;
for (int i=1;i<=t;++i) b[i]=a[i];
for (int i=1;i<=t;++i) b[i+t]={a[i].a?mo-a[i].a:0,m+1+a[i].b};
sort(b+1,b+t+t+1,cmp);
for (int i=1;i<=t+t;++i){
if (b[i].b>R) break;
if (b[i].b!=b[i-1].b) a[++k]={0,b[i].b};
a[k].a+=b[i].a; if (a[k].a>=mo) a[k].a-=mo;
}
t=k;
}
printf("%d",(get(R)-get(L-1)+mo)%mo);
return 0;
}
荔枝

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: