[生成函数][DFT][NTT] Hdu P6067 Big Integer

会有一股神秘感。 提交于 2019-11-27 13:01:24

 

 

 题解

 

代码

 1 #include <cstdio>
 2 #include <istream>
 3 #define ll long long
 4 using namespace std;
 5 const ll N=200010,mo=786433;
 6 int T,n,m,k,x,y,sum,num[N],f[N],len,L,rev[N],v[10][N];
 7 ll a[10][N],inv[mo],fac[N],ny[N],ans[N],p[N],P[N];
 8 char s[N];
 9 ll ksm(ll a,ll b) { ll r=1; for (;b;b>>=1,a=a*a%mo) if (b&1) r=r*a%mo; return r; }
10 void ntt(ll *a,int len,int f)
11 {
12     for (int i=0;i<len;i++) if (rev[i]>i) swap(a[i],a[rev[i]]);
13     for (int i=2;i<=len;i<<=1)
14     {
15         ll r,m=i>>1;
16         if (f==1) r=p[i]; else r=P[i];
17         for (int j=0;j<len;j+=i)
18         {
19             ll R=1;
20             for (int k=0;k<m;k++,R=R*r%mo)
21             {
22                 ll x=a[j+k],y=a[j+k+m]*R%mo;
23                 a[j+k]=(x+y)%mo,a[j+k+m]=(x-y+mo)%mo;
24             }
25         }
26     }
27     if (f==-1) { ll r=ksm(len,mo-2); for (int i=0;i<len;i++) a[i]=a[i]*r%mo; }
28 }
29 int main()
30 {
31     
32     fac[0]=ny[0]=1;
33     for (int i=1;i<N;i++) p[i]=ksm(10,(mo-1)/i),P[i]=ksm(p[i],mo-2);
34     for (int i=0;i<mo;i++) inv[i]=ksm(i,mo-2);
35     for (int i=1;i<N;i++) fac[i]=fac[i-1]*(ll)i%mo;
36     ny[N-1]=ksm(fac[N-1],mo-2);
37     for (int i=N-2;i;i--) ny[i]=ny[i+1]*(ll)(i+1)%mo;
38     scanf("%d",&T);
39     while (T--) 
40     {
41         scanf("%d%d%d",&n,&m,&k),n--,sum=0;
42         for (int i=0;i<n;i++) 
43         {
44             scanf("%s",s);
45             for (int j=0;j<=m;j++) v[i][j]=s[j]-'0';
46         }
47         for (len=1,L=-1;len<=n*m;len*=2) L++;
48         for (int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L);
49         for (int i=0;i<len;i++) num[i]=0,f[i]=1;
50         for (int i=0;i<n;i++) 
51         {
52             for (int j=0;j<len;j++) a[i][j]=0;
53             for (int j=0;j<=m;j++) if (v[i][j]) a[i][j]=ny[j];
54             ntt(a[i],len,1); 
55             for (int j=0;j<len;j++) if (a[i][j]) f[j]=f[j]*a[i][j]%mo; else num[j]++;
56         }
57         for (int i=0;i<len;i++) ans[i]=num[i]?0:f[i];
58         for (int x,y;k;k--)
59         {
60             scanf("%d%d",&x,&y),x--;
61             for (int i=0;i<len;i++) if (a[x][i]) f[i]=f[i]*inv[a[x][i]]%mo; else num[i]--;
62             ll flag;
63             if (v[x][y]==1) flag=-1; else flag=1;
64             v[x][y]^=1;
65             ll r=1,R=ksm(p[len],y);
66             for (int i=0;i<len;i++,r=r*R%mo) a[x][i]=(a[x][i]+flag*inv[fac[y]]*r%mo+mo)%mo;
67             for (int i=0;i<len;i++) if (a[x][i]) f[i]=f[i]*a[x][i]%mo; else num[i]++;
68             for (int i=0;i<len;i++) ans[i]=(ans[i]+(num[i]?0:f[i]))%mo;
69         }
70         ntt(ans,len,-1);
71         for (int i=1;i<len;i++) sum=(sum+ans[i]*fac[i]%mo)%mo;
72         printf("%lld\n",sum);
73     }
74 }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!