Description
我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树。对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为1的结点是叶子结点;对于任一点权大于1的结点u,u的孩子数目deg[u]属于集合D,且u的点权等于这些孩子结点的点权之和。
给出一个整数s,你能求出根节点权值为s的神犇多叉树的个数吗?请参照样例以更好的理解什么样的两棵多叉树会被视为不同的。
我们只需要知道答案关于950009857(453*2^21+1,一个质数)取模后的值。
Input
第一行有2个整数s,m。
第二行有m个互异的整数,d[1],d[2],…,d[m],为集合D中的元素。
Output
输出一行仅一个整数,表示答案模950009857的值。
Sample Input
4 2
2 3
2 3
Sample Output
10
HINT
数据规模:
1<=m<s<=10^5, 2<=d[i]<=s,有3组小数据和3组大数据。
1<=m<s<=10^5, 2<=d[i]<=s,有3组小数据和3组大数据。
获得新知识:拉格朗日反演

不知道怎么证
结论还是比较好记的
获得新模板:fft的基本操作

//%std
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define lovelive long long
#define lc son[x][0]
#define rc son[x][1]
#define lowbit(x) (x&(-x))
#define pt vc
const lovelive mod=950009857,G=7;
const int N=1e5+100;
void read(lovelive &x)
{
lovelive p=1;
x=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
p=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-48;
c=getchar();
}
x*=p;
}
lovelive A[N<<2],B[N<<2],tmp[N<<2],f[N<<2],g[N<<2];
lovelive pow1(lovelive x,lovelive k)
{
lovelive r=1;
if(k<0)
k+=mod-1;
while(k)
{
if(k&1)
r*=x;
x*=x;
r%=mod;
x%=mod;
k>>=1;
}
return r;
}
void change(lovelive y[],int len)
{
for(lovelive i=1,j=len>>1,k;i<len-1;i++)
{
if(i<j)
swap(y[i],y[j]);
k=len>>1;
while(j>=k)
{
j-=k;
k>>=1;
}
if(j<=k)
j+=k;
}
}
void fft(lovelive y[],int len,int on)
{
change(y,len);
for(int h=2;h<=len;h<<=1)
{
lovelive wn=pow1(G,(mod-1)*on/h);
for(int j=0;j<len;j+=h)
{
lovelive w=1;
for(int i=j;i<j+(h>>1);i++)
{
lovelive u=y[i],v=w*y[i+(h>>1)]%mod;
y[i]=(u+v)%mod;
y[i+(h>>1)]=(u-v+mod)%mod;
w=w*wn%mod;
}
}
}
if(on==-1)
{
lovelive inv=pow1(len,-1);
for(int i=0;i<len;i++)
y[i]=y[i]*inv%mod;
}
}
void find_inv(lovelive a[],lovelive b[],int len)
{
if(len==1)
{
b[0]=pow1(a[0],-1);b[1]=0;
return;
}
find_inv(a,b,len>>1);
for(int i=0;i<len;i++)
f[i]=a[i];
memcpy(f,a,sizeof(b[0])*len);
memset(f+len,0,sizeof(f[0])*len);
fft(f,len<<1,1);
fft(b,len<<1,1);
for(int i=0;i<len<<1;i++)
f[i]=b[i]*(2+mod-f[i]*b[i]%mod)%mod;
fft(f,len<<1,-1);
for(int i=0;i<len;i++)
b[i]=f[i];
memset(b+len,0,sizeof(b[0])*len);
return;
}
lovelive inv[N<<2],jc[N<<2];
void find_ln(lovelive a[],lovelive b[],int len)
{
// for(int i=0;i<len;i++)
// g[i]=0;
find_inv(a,g,len);
for(lovelive i=0;i<len-1;i++)
b[i]=a[i+1]*(i+1)%mod;
// b[len]=0;
fft(g,len<<1,1);
fft(b,len<<1,1);
for(int i=0;i<len<<1;i++)
b[i]=b[i]*g[i]%mod;
fft(b,len<<1,-1);
for(int i=len-1;i;i--)
b[i]=b[i-1]*(inv[i]*jc[i-1]%mod)%mod;
b[0]=0;
memset(b+len,0,sizeof(b[0])*len);
memset(g,0,sizeof(g[0])*len<<1);
}
void find_exp(lovelive a[],lovelive b[],int len)
{
if(len==1)
{
b[0]=1;b[1]=0;
return;
}
find_exp(a,b,len>>1);
memset(tmp,0,sizeof(tmp[0])*len<<1);
find_ln(b,tmp,len);
for(int i=0;i<len;i++)
tmp[i]=((i==0)+(mod-tmp[i])+a[i])%mod;
fft(b,len<<1,1);
fft(tmp,len<<1,1);
for(int i=0;i<len<<1;i++)
b[i]=b[i]*tmp[i]%mod;
fft(b,len<<1,-1);
for(int i=0;i<len;i++)
b[i+len]=0;
return;
}
void prepare(int len)
{
jc[0]=inv[0]=1;
for(lovelive i=1;i<=len;i++)
jc[i]=jc[i-1]*i%mod;
inv[len]=pow1(jc[len],-1);
for(lovelive i=len-1;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
lovelive C[N<<2];
void find_kth(lovelive a[],lovelive b[],lovelive k,int len)
{
find_ln(a,C,len);
for(int i=0;i<len;i++)
C[i]=C[i]*k%mod;
find_exp(C,b,len);
}
int main()
{
lovelive n,s,x,len=1;
read(s);read(n);
for(int i=1;i<=n;i++)
{
read(x);
A[x-1]=mod-1;
}
A[0]++;
while(len<=s)
len<<=1;
prepare(len);
find_inv(A,B,len);
memset(A,0,sizeof(A));
find_kth(B,A,s,len);
cout<<A[s-1]*pow1(s,-1)%mod<<"\n";
// read(n);
// for(int i=0;i<=n;i++)
// read(A[i]);
// while(len<=n)
// len<<=1;
// prepare(len);
// find_exp(A,B,len);
// for(int i=0;i<=n;i++)
// printf("%lld ",B[i]);
return 0;
}
/*
3 2
2 3
4 3
2 3 4
100000 4
2 3 4 5
*/
来源:https://www.cnblogs.com/NicoDafaGood/p/8954845.html
