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;
}
View Code

 

posted @ 2018-05-08 22:21  NicoDafaGood  阅读(154)  评论(0编辑  收藏  举报