bzoj 3684: 大朋友和多叉树 生成函数
来源:互联网 发布:淘宝联盟没有佣金原因 编辑:程序博客网 时间:2024/06/08 08:25
关于生成函数,可以见金策爷的课件。
设F为多叉树的生成函数,第n项表示根权值为n时的方案数;C为儿子的生成函数,那么有:
F(x)=Σi∈(S)F(x)^i+x,也就是F(x)=C(F(x))+x,移项得到F(x)-C(F(x))=x,那么令G(x)=x-C(x),就有:G(F(x))=x,因此F(x)是G(x)的复合逆。然后运用拉格朗日反演:
[x^n]F(x)=1/n(x^(n-1))(x/G(x))^n。。证明课件里面也没有讲QAQ。
就变成求逆和求多项式的n次了。。。前面的用多项式求逆,后面的可以拆成epx(ln(x/G(x))*n),具体课件里有。
然后就变成抄代码时间辣T_T。
AC代码如下:
#include<iostream>#include<cstdio>#include<cstring>#define ll long long#define mod 950009857#define N 270005using namespace std;int f[N],g[N],c[N],h[N],q[N],inv[N],pos[N],na[N];int ksm(int x,int y){int t=1; for (; y; y>>=1,x=(ll)x*x%mod) if (y&1) t=(ll)t*x%mod;return t;}void getpos(int n){int cnt=0,i,j,k;for (k=1; k<n; k<<=1) cnt++;for (i=0; i<n; i++){k=i; pos[i]=0;for (j=1; j<=cnt; j++,k>>=1) pos[i]=pos[i]<<1|(k&1);}}void fnt(int *a,int n,int p){int i,j,k,w,wn,u,v;//for (i=0; i<n; i++) cout<<a[i]<<' '; puts("");for (i=0; i<n; i++) na[pos[i]]=a[i]; memcpy(a,na,sizeof(a[0])*n);for (k=1; k<n; k<<=1){wn=ksm(7,(ll)((mod-1)>>1)/k*p%(mod-1));for (i=0; i<n; i+=(k<<1)){w=1;for (j=i; j<i+k; j++,w=(ll)w*wn%mod){u=a[j]; v=(ll)a[j+k]*w%mod;a[j]=(u+v)%mod; a[j+k]=(u+mod-v)%mod;}}}//for (i=0; i<n; i++) cout<<a[i]<<' ';puts("");puts("");if (p+2==mod)for (i=0; i<n; i++) a[i]=(ll)a[i]*inv[n]%mod;}void solve_inv(int *a,int *b,int n){if (n==1){ b[0]=ksm(a[0],mod-2); return; }solve_inv(a,b,n>>1); int i;memcpy(c,a,sizeof(a[0])*n); memset(c+n,0,sizeof(c[0])*n);getpos(n<<1);fnt(b,n<<1,1); fnt(c,n<<1,1);for (i=0; i<(n<<1); i++) b[i]=(ll)b[i]*(2-(ll)b[i]*c[i]%mod+mod)%mod;fnt(b,n<<1,mod-2); memset(b+n,0,sizeof(b[0])*n);}void solve_ln(int *a,int *b,int n){memset(q,0,sizeof(q[0])*(n<<1)); solve_inv(a,q,n);memset(c,0,sizeof(c[0])*(n<<1)); int i;for (i=0; i+1<n; i++) c[i]=(ll)a[i+1]*(i+1)%mod;getpos(n<<1);fnt(q,n<<1,1); fnt(c,n<<1,1);for (i=0; i<(n<<1); i++) b[i]=(ll)q[i]*c[i]%mod;fnt(b,n<<1,mod-2);for (i=n-1; i; i--) b[i]=(ll)b[i-1]*inv[i]%mod; b[0]=0;memset(b+n,0,sizeof(b[0])*n);}void solve_exp(int *a,int *b,int n){if (n==1){ b[0]=1; return; }solve_exp(a,b,n>>1); int i;memset(h,0,sizeof(h[0])*(n<<1)); solve_ln(b,h,n);for (i=0; i<n; i++) h[i]=(a[i]-h[i]+mod)%mod; h[0]=(h[0]+1)%mod;getpos(n<<1);fnt(b,n<<1,1); fnt(h,n<<1,1);for (i=0; i<(n<<1); i++) b[i]=(ll)b[i]*h[i]%mod;fnt(b,n<<1,mod-2); memset(b+n,0,sizeof(b[0])*n);}int main(){int i,x,n,len,m; scanf("%d%d",&len,&m);for (i=1; i<=m; i++){scanf("%d",&x); f[x-1]=mod-1;}f[0]=inv[1]=n=1;while (n<=len) n<<=1;for (i=2; i<=(n<<1); i++) inv[i]=mod-(ll)inv[mod%i]*(mod/i)%mod;solve_inv(f,g,n);memset(f,0,sizeof(f)); solve_ln(g,f,n);for (i=0; i<n; i++) f[i]=(ll)f[i]*len%mod;memset(g,0,sizeof(g)); solve_exp(f,g,n);printf("%d\n",(ll)g[len-1]*ksm(len,mod-2)%mod);return 0;}
by lych
2016.4.17
0 0
- bzoj 3684: 大朋友和多叉树 生成函数
- BZOJ 3684 大朋友和多叉树(生成函数+FFT)
- BZOJ 3684 大朋友和多叉树 FFT+拉格朗日反演
- BZOJ 3684 大朋友与多叉树 多项式求幂/求exp+拉格朗日反演
- BZOJ 3625 小朋友和二叉树(生成函数+FFT)
- BZOJ 3456 城市规划 NTT 生成函数计数 ***
- [生成函数 FFT] BZOJ 3771 Triple
- bzoj 3028: 食物 (生成函数)
- bzoj 3027: [Ceoi2004]Sweet (生成函数)
- BZOJ 4555 求和(生成函数+FFT)
- 朋友函数
- bzoj 4802: 欧拉函数 大整数分解
- 【 bzoj 3992 】 [SDOI2015]序列统计 - NTT 生成函数
- [生成函数 FFT 分块] BZOJ 3509 [CodeChef] COUNTARI
- [期望 生成函数 卷积 导数] BZOJ 4001 [TJOI2015]概率论
- bzoj 3771: Triple (容斥原理+生成函数+FFT)
- bzoj 2287: 【POJ Challenge】消失之物 生成函数+背包
- [生成函数][NTT][多项式求逆]BZOJ 3456: 城市规划
- cassandra 如何写数据以及放置副本
- 简单动态规划
- Android中的soundpool小结
- wpa_supplicant 连接不上可能几种原因
- xml与json的对比
- bzoj 3684: 大朋友和多叉树 生成函数
- 图片加水印
- FireMonkey下类似手机QQ侧滑菜单的实现
- Java解析Json缺少jar报错:org/apache/commons/lang/exception/NestableRuntimeException
- hive jdbc程序开发
- php之重载__get() __set() isset() unset() __call() __callStatic()
- 剑指offer(十)之矩形覆盖
- xmpp开发IM即时通讯系列(二)--即时通讯服务器搭建(2)openfire服务器搭建
- 一个炫酷的SearchView搜索动画库