2179: FFT快速傅立叶
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2803 Solved: 1431
[ Submit][ Status][ Discuss]
Description
给出两个n位10进制整数x和y,你需要计算x*y。
Input
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
Output
输出一行,即x*y的结果。
Sample Input
1
3
4
3
4
Sample Output
12
数据范围:
n<=60000
数据范围:
n<=60000
HINT
Source
上一个快速数论变换,在FFT基础上稍作修改就行
模数取1004535809,原根是3
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 2E5 + 10;
typedef long long LL;
const LL mo = 1004535809;
LL g[maxn],A[maxn],B[maxn],C[maxn],D[maxn];
int n,N,L,rev[maxn],Num[maxn];
char ch[maxn];
LL ksm(LL x,LL y)
{
LL ret = 1;
for (; y; y >>= 1LL) {
if (y&1LL) ret = ret*x%mo;
x = x*x%mo;
}
return ret;
}
void NTT(LL *a,int on)
{
for (int i = 0; i < N; i++) D[i] = a[rev[i]];
for (int i = 0; i < N; i++) a[i] = D[i];
for (int k = 2; k <= N; k <<= 1)
for (int i = 0; i < N; i += k) {
int w = 0;
for (int j = i; j < i + (k>>1); j++) {
LL u = a[j];
LL t = g[w]*a[j+(k>>1)]%mo;
a[j] = (u + t)%mo;
a[j+(k>>1)] = (u - t + mo)%mo;
w += (N/k);
}
}
if (on == -1) {
LL inv = ksm(N,mo-2);
for (int i = 0; i < N; i++)
a[i] = a[i]*inv%mo;
}
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
for (N = 1; N <= n; N <<= 1,++L);
N <<= 1; ++L;
for (int i = 0; i < N; i++) {
int len = 0;
for (int x = i; x; x >>= 1) Num[len++] = x&1;
for (int j = 0; j < L; j++)
rev[i] <<= 1,rev[i] |= Num[j];
}
scanf("%s",ch);
for (int i = 0; i < n; i++)
A[i] = ch[n - i - 1] - '0';
scanf("%s",ch);
for (int i = 0; i < n; i++)
B[i] = ch[n - i - 1] - '0';
g[0] = g[N] = 1;
g[1] = ksm(3,(mo - 1)/(1LL*N));
for (int i = 2; i < N; i++)
g[i] = g[i-1]*g[1]%mo;
NTT(A,1); NTT(B,1);
for (int i = 0; i < N; i++)
C[i] = A[i]*B[i]%mo;
for (int i = 0; i < N/2; i++)
swap(g[i],g[N - i]);
NTT(C,-1);
for (int i = 0; i < N; i++) {
C[i + 1] += C[i]/10LL;
C[i] %= 10LL;
}
int pos;
for (int i = N - 1; i >= 0; i--)
if (C[i]) {pos = i; break;}
for (int i = pos; i >= 0; i--)
printf("%d",C[i]);
return 0;
}