2179: FFT快速傅立叶 - #include <Seter> - using namespace Orz;
2179: FFT快速傅立叶
http://www.zybbs.org/JudgeOnline/problem.php?id=2179
| RunID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
| 175346 | Seter | 2179 | Accepted | 1756 kb | 1120 ms | C/Edit | 1597 B | 2011-11-22 19:17:39 |
于是花了3个小时写了个分治版的大数乘法……压9位后常数果然巨小,60000位时比FFT还快一点!膜拜AC大神208MS稳居榜首!
用FFT过掉后看到TIM是用分治的……于是回去想了好久……终于想出来了……
多项式(Ax+B)(Cx+D)=ACxx+BD+(ADx+BCx)=ACxx+BD+[(A+B)(C+D)-AC-BD]x
令x=10^(n/2),于是每次算出AC,BD,(A+B)(C+D)即可。T(n)=3T(n/2)+O(n)
当n较小时直接暴力出解……测了下n<=10时效果最好,压3位的话60效果最好。
#include <stdio.h>
#include <string.h>
#define logn 10
#define maxn 6670
#define base 1000000000
int re[maxn<<1],a[maxn],b[maxn],ABCD[logn][maxn],A[logn][maxn],B[logn][maxn],N;
char str[120003];
multi(re,a,b,n,d)int *re,*a,*b,n,d;{
int i,j=0,ln=n>>1,rn=n-ln,l;long long t;
memset(re,0,n<<3);
if(n<=10){
for(i=-1;++i!=n;)for(j=-1;++j!=n;re[i+j]=t-l*base)re[i+j+1]+=l=(t=(long long)a[i]*b[j]+re[i+j])/base;
for(l=n<<1;--l&&!re[l];);return l;
}memset(A[d],0,rn+1<<2);memset(B[d],0,rn+1<<2);
for(i=-1;++i!=ln;){
A[d][i+1]+=(A[d][i]+=a[i]+a[i+ln])/base;A[d][i]%=base;
B[d][i+1]+=(B[d][i]+=b[i]+b[i+ln])/base;B[d][i]%=base;
}if(rn==ln+1){
A[d][rn]+=(A[d][i]+=a[i<<1])/base;A[d][i]%=base;
B[d][rn]+=(B[d][i]+=b[i<<1])/base;B[d][i]%=base;
}l=multi(ABCD[d],A[d],B[d],rn+1,d+1);
for(i=multi(B[d],a,b,ln,d+1)+1;i--;re[i]=B[d][i])ABCD[d][i]-=B[d][i];
for(i=multi(A[d],a+ln,b+ln,rn,d+1)+1;i--;re[i+(ln<<1)]+=A[d][i])ABCD[d][i]-=A[d][i];
for(i=-1;i++!=l+1;){
ABCD[d][i+1]+=ABCD[d][i]/base;
if((ABCD[d][i]%=base)<0)ABCD[d][i]+=base,ABCD[d][i+1]--;
if(ABCD[d][i])re[i+ln]+=ABCD[d][i];
}for(i=-1;++i!=n<<1;(re[i]%=base)&&(j=i))re[i+1]+=re[i]/base;
return j;
}main(){
int i,p,k,d;
scanf("%d",&N);d=N%9?9-N%9:0;fread(str,1,(N<<1)+2,stdin);
for(k=(N+d)/9-1,p=d,i=N;i--;(++p==9)&&(p=0,k--)){
a[k]=a[k]*10+str[N-i]-48;
b[k]=b[k]*10+str[(N<<1)-i+1]-48;
}for(N=(N+d)/9,printf("%d",re[i=multi(re,a,b,N,0)]);i--;printf("%09d",re[i]));putchar('\n');
return 0;
}
By Seter
2012年6月12日 01:58
现在才会FFT的傻×表示压5位FFT和这个时间差不多T_T
2012年6月14日 14:34
跪烂了……不会实数FFT。。。