1. 程式人生 > >NTT模板

NTT模板

a* 單位根 pow cout print ring gpo void pos

如題(大數乘法)。把FFT種的n次單位根換成模意義下的“n次單位原根”,即$G^{\frac{p-1}{n}}$即可。

//#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
//#include<math.h>
//#include<time.h>
//#include<complex>
#include<algorithm>
using namespace std;

int n,m,wei;
#define maxn 262222
const
int mod=998244353,G=3; int a[maxn],b[maxn],c[maxn],rev[maxn]; int powmod(int a,int b) { int ans=1; while (b) { if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b>>=1; } return ans; } void dft(int *a,int n,int type) { for (int i=0;i<n;i++) if (i<rev[i]) {int
t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;} for (int i=1;i<n;i<<=1) { int w=powmod(G,(mod-1)/(i*2)); if (type==-1) w=powmod(w,mod-2); for (int j=0,p=i<<1;j<n;j+=p) { int t=1; for (int k=0;k<i;k++,t=1ll*t*w%mod) {
int tmp=a[j+k+i]*1ll*t%mod; a[j+k+i]=(a[j+k]-tmp+mod)%mod; a[j+k]=(a[j+k]+tmp)%mod; } } } } void ntt(int *a,int *b,int *c) { if (!rev[1]) for (int i=0;i<n;i++) { rev[i]=0; for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1); } // for (int i=0;i<n;i++) cout<<rev[i]<<‘ ‘;cout<<endl; dft(a,n,1); dft(b,n,1); for (int i=0;i<n;i++) c[i]=1ll*a[i]*b[i]%mod; dft(c,n,-1); int inv=powmod(n,mod-2); for (int i=0;i<n;i++) c[i]=1ll*inv*c[i]%mod; } char sa[maxn],sb[maxn]; int main() { scanf("%s%s",sa,sb); n=strlen(sa)-1; m=strlen(sb)-1; for (int i=0;i<=n;i++) a[i]=sa[n-i]-0; for (int i=0;i<=m;i++) b[i]=sb[m-i]-0; m=m+n; for (n=1,wei=0;n<=m;n<<=1,wei++); ntt(a,b,c); for (int i=0;i<=m;i++) c[i+1]+=c[i]/10,c[i]%=10; if (c[m+1]) m++; for (int i=m;i>=0;i--) printf("%d",c[i]); return 0; }

NTT模板