Wannafly挑战赛14 F
Shero在秘密基地有一个专门研究活骸化的实验室。
实验室里面有一排从0开始标号的培养皿,初始的时候只有0号培养皿中有1个细胞。
因为是虚拟实验,所以可以认为培养皿有无限个。
Shero观察发现,来自异世界的细胞分裂速度似乎要比的一般的细胞迅速得多:
具体来说,第n天第k个培养皿中会有2k * C(n,k)个细胞(异世界的细胞当然有能力到处跑啦
为了找到活骸化的原因,Shero给出了一个参数m,现在他想知道在第n天对于每一个0<=i<2m,所有下标mod 2m为i的培养皿中的细胞数量总和是多少
输入描述:
第一行两个正整数n,m
输出描述:
设ans[i]表示下标mod 2^m为i的培养皿中的细胞总数
一行一个正整数输出
mod 998244353的值
示例1
输入
4 2
输出
3738937
心态崩了
挂一道我没有做起的fft板子题
首先看到组合数和次幂
发现可能跟二项式展开有关系
然后发现2^k*C(n,k)就是(2x+1)^n的x^k的系数
然后题目上面求所有次数在模2^m意义下同余的系数和
仔细想想
我们可以给x代入一些我们需要的值
如果x^(2^m)%998244353==1
这个可以用单位根搞定
那不就好了
llj觉得那样我们就可以得到一个2^m元方程
然后我们就可以高斯消元啦
只要我们可以找到一种O(n)的消元方式就好啦
这道题这么特殊
一定可以的!!!!
然后我就浪费了一晚上
再仔细想了想觉得这样不行
如果我知道
2222303=单位根^k
那么我只用代入一次就好啦!!!!
非常的开心
但是发现原根=3时2222303!=单位根的整数次幂
然后我觉得这是原根的问题
然后我就写了个暴力枚举所有原根再BSGS计算2222303是否是单位根的整数次幂
一个小时过去后我再次放弃了
然后看看其他选手的代码长度
????
为什么这么短????
再次仔细想一想
将(2x+1)^n变成一个2^m-1次的多项式
其中由于代入的所有x满足x^(2^m)==1
所以这个2^m-1次的多项式的第k项是(2x+1)^n所有次数与k对模2^m同余的项的系数和
我们发现这就是ans[]
问题就成了
我们可以轻松的知道每个点的值
我们要算每一项的系数
....
然后发现这是个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=998244353; const lovelive G=3; const int N=1e6+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 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(int 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 tmp=pow1(len,-1); for(int i=0;i<len;i++) y[i]=y[i]*tmp%mod; } } lovelive ans[N<<2]; int main() { lovelive n,m; read(n);read(m); lovelive w=1,wn=pow1(G,(mod-1)/(1<<m)); for(int i=0;i<(1<<m);i++) { ans[i]=pow1(2*w+1,n); w=w*wn%mod; } fft(ans,1<<m,-1); w=1,wn=2222303; lovelive r=0; for(int i=0;i<(1<<m);i++) { r+=ans[i]*w%mod; r%=mod; w=w*wn%mod; } cout<<r<<"\n"; return 0; }