zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    【23设计模式】总结
    【JAVA】内部类,内部接口
    【JAVA】接口
    【JAVA】抽象类,抽象方法
    【JAVA】类加载器
    【JAVA】枚举
    【JAVA】序列化
    【JAVA】异常笔记
    汇编笔记_第十一章
    汇编笔记_第十章
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7545466.html
Copyright © 2011-2022 走看看