大佬博客
和FFT一样都是快速求多项式乘法的,但是这个用的是整数,没有精度误差,运算起来也会更快。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int maxn=1<<18;
const int P=(479<<21)+1;//大素数
const int G=3;
const int sz=20;
int len;
LL wn[sz],a[maxn],b[maxn];
char s1[maxn],s2[maxn];
LL quick_mod(LL a,LL b,LL mod)
{
LL res=1;
a%=mod;
while(b)
{
if(b&1)
res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
void get_wn()
{
for(int i=0; i<sz; i++)
{
int t=1<<i;
wn[i]=quick_mod(G,(P-1)/t,P);
}
}
void init()
{
len=1;
int len1=strlen(s1),len2=strlen(s2);
while(len<=len1*2||len<=len2*2) len<<=1;
for(int i=0; i<len; i++)
{
if(i<len1) a[i]=(LL)s1[len1-i-1]-'0';
else a[i]=0;
if(i<len2) b[i]=(LL)s2[len2-i-1]-'0';
else b[i]=0;
}
}
void Rader(LL a[],int len)//雷德算法--倒位序
{
int j=len>>1;
for(int i=1; i<len-1; i++)
{
if(i<j) swap(a[i],a[j]);
int k=len>>1;
while(j>=k)
{
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
}
void NTT(LL a[],int len,int on)//快速数论变换
{
Rader(a,len);
int id=0;
for(int h=2; h<=len; h<<=1)
{
id++;
for(int j=0; j<len; j+=h)
{
LL w=1;
for(int k=j; k<j+h/2; k++)
{
LL u=a[k]%P;
LL t=w*a[k+h/2]%P;
a[k]=(u+t)%P;
a[k+h/2]=(u-t+P)%P;
w=w*wn[id]%P;
}
}
}
if(on==-1)
{
for(int i=1; i<len/2; i++)
swap(a[i],a[len-i]);
LL inv=quick_mod(len,P-2,P);
for(int i=0; i<len; i++)
a[i]=a[i]*inv%P;
}
}
void Conv(LL a[],LL b[],int len)//求卷积
{
NTT(a,len,1);
NTT(b,len,1);
for(int i=0; i<len; i++)
a[i]=a[i]*b[i]%P;
NTT(a,len,-1);
}
void solve(LL a[],int len)
{
for(int i=0; i<len; i++)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
int f=0;
for(int i=len-1; i>=0; i--)
{
if(a[i])
{
for(int j=i; j>=0; j--)
f=1,printf("%d",a[j]);
break;
}
}
if(!f) printf("0");
printf("\n");
}
int main()
{
get_wn();
while(~scanf("%s%s",s1,s2))
{
init();
Conv(a,b,len);
solve(a,len);
}
}