2179: FFT快速傅立叶
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 3468 Solved: 1820
[Submit][Status][Discuss]
Description
给出两个n位10进制整数x和y,你需要计算x*y。
Input
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
Output
输出一行,即x*y的结果。
Sample Input
1
3
4
Sample Output
12
数据范围:
n<=60000
【分析】
NTT解法
【代码】
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mod=479*(1<<21)+1;
const int mxn=400005;
char s[mxn];
int n,m,L;
int a[mxn],b[mxn],R[mxn];
inline int ksm(int a,int k)
{
int res=1;
while(k)
{
if(k&1) res=((ll)res*a)%mod;
a=((ll)a*a)%mod;
k>>=1;
}
return res;
}
inline void NTT(int *a,int f)
{
int i,j,k;
fo(i,0,n-1) if(i<R[i]) swap(a[i],a[R[i]]);
for(i=1;i<n;i<<=1)
{
int wn=ksm(3,(mod-1)/(i<<1));
for(j=0;j<n;j+=(i<<1))
{
int w=1;
for(k=0;k<i;k++,w=((ll)w*wn)%mod)
{
int x=a[j+k],y=((ll)w*a[j+k+i])%mod;
a[j+k]=(x+y)%mod,a[j+k+i]=(x-y+mod)%mod;
}
}
}
if(f==-1)
{
reverse(a+1,a+n);
int rev=ksm(n,mod-2);
fo(i,0,n-1) a[i]=((ll)a[i]*rev)%mod;
}
}
int main()
{
int i,j,k;
scanf("%d",&n);
n--;
scanf("%s",s);
fo(i,0,n) a[i]=s[n-i]-'0';
scanf("%s",s);
fo(i,0,n) b[i]=s[n-i]-'0';
m=2*n;for(n=1;n<=m;n<<=1) L++;
fo(i,0,n-1) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
NTT(a,1),NTT(b,1);
fo(i,0,n) a[i]=((ll)a[i]*b[i]%mod);
NTT(a,-1);
fo(i,0,m) if(a[i]>=10)
{
a[i+1]+=a[i]/10,a[i]%=10;
if(i==m) m++;
}
while(!a[m]) m--;
for(i=m;i>=0;i--) printf("%d",a[i]);
return 0;
}