【NTT】hdu1402 A * B Problem Plus

2^k+1r
k
g
3 1 1 2
5 1 2 2
17 1 4 3
97 3 5 5
193 3 6 5
257 1 8 3
7681 15 9 17
12289 3 12 11
40961 5 13 3
65537 1 16 3
786433 3 18 10
5767169 11 19 3
7340033 7 20 3
23068673 11 21 3
104857601 25 22 3
167772161 5 25 3
469762049 7 26 3
998244353 119 23 3
1004535809 479 21 3
2013265921 15 27 31
2281701377 17 27 3
3221225473 3 30 5
75161927681 35 31 3
77309411329 9 33 7
206158430209 3 36 22
2061584302081 15 37 7
2748779069441 5 39 3
6597069766657 3 41 5
39582418599937 9 42 5
79164837199873 9 43 5
263882790666241 15 44 7
1231453023109121 35 45 3
1337006139375617 19 46 3
3799912185593857 27 47 5
4222124650659841 15 48 19
7881299347898369 7 50 6
31525197391593473 7 52 3
180143985094819841 5 55 6
1945555039024054273 27 56 5
4179340454199820289 29 57 3

以上是一份NTT专用模数与原根的对照表……

然后从网上爬了一份NTT代码:http://www.cnblogs.com/candy99/p/6641972.html

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define N ((1<<18)+5)
#define MOD 1004535809ll
ll Quick_Pow(ll a,ll p){
	if(p==0){
		return 1ll;
	}
    ll res=Quick_Pow(a,p>>1);
    res=res*res%MOD;
    if((p&1ll)==1ll){
    	res=(a%MOD*res)%MOD;
    }
    return res;
}
struct NTT{
	int n,rev[N];
	ll g;
	void ini(int lim) {
		g=3;//1004535809,998244353的原根都是3
		n=1;
		int k=0;
		while(n<lim){
			n<<=1;
			++k;
		}
		for(int i=0;i<n;++i){
			rev[i]=((rev[i>>1]>>1)|((i&1)<<(k-1)));
		}
	}
	void dft(ll a[],int DFT) {
		for(int i=0;i<n;++i){
			if(i<rev[i]){
				swap(a[i],a[rev[i]]);
			}
		}
		for(int l=2;l<=n;l<<=1){
			int m=l>>1;
			ll wn=Quick_Pow(g,DFT==1 ? (MOD-1ll)/(ll)l : MOD-1ll-(MOD-1ll)/(ll)l);
			for(int i=0;i<n;i+=l){
				ll w=1;
				for(int k=0;k<m;++k){
					ll t=w*a[i+k+m]%MOD;
					a[i+k+m]=(a[i+k]-t+MOD)%MOD;
					a[i+k]=(a[i+k]+t)%MOD;
					w=w*wn%MOD;
				}
			}
		}
		if(DFT==-1){
			ll inv=Quick_Pow(n,MOD-2ll);
			for(int i=0;i<n;++i){
				a[i]=a[i]*inv%MOD;
			}
		}
	}
	void mul(ll a[],ll b[],int len) {
		ini(len);
		dft(a,1);
		dft(b,1);
		for(int i=0;i<n;++i){
			a[i]=a[i]*b[i];
		}
		dft(a,-1);
	}
}ntt;
int len1,len2,len,c[N];
ll a[N],b[N];
char s1[N],s2[N];
int main() {
//	freopen("ntt.in","r",stdin);
	while(scanf("%s%s",s1,s2)!=EOF){
		memset(c,0,sizeof(c));
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		len1=strlen(s1);
		len2=strlen(s2);
		for(int i=0;i<len1;++i){
			a[i]=s1[len1-i-1]-'0';
		}
		for(int i=0;i<len2;++i){
			b[i]=s2[len2-i-1]-'0';
		}
		len=len1+len2-1;
		ntt.mul(a,b,len);
		for(int i=0;i<len;++i){
			c[i]=a[i];
		}
		for(int i=0;i<len;++i){
			c[i+1]+=c[i]/10;
			c[i]%=10;
		}
//		if(c[len]){
//			++len;
//		}//两个数乘积的长度要么是A+B-1,要么是A+B。
//		for(int i=len-1;i>=0;--i){
//			printf("%d",c[i]);
//		}
//		puts("");
		for(int i=len;i>=0;--i){
			if(c[i]!=0 || i==0){
				for(int j=i;j>=0;--j){
					printf("%d",c[j]);
				}
				puts("");
				break;
			}
		}
	}
	return 0;
}
posted @ 2017-09-18 21:49  AutSky_JadeK  阅读(256)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト