spoj Fast Multiplication

题意:乘法

要用nlogn的fft乘法。

//#pragma comment(linker,"/STACK:1024000000,1024000000") 
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include <stack>
using namespace std;
typedef long long lon;
//#define ll long long
//#define inf 1000000000
//#define mod 1000000007
#define N 350000
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
const lon SZ=100010,INF=0x7FFFFFFF;
const double pi = acos(-1);
char s1[N>>1],s2[N>>1];
double rea[N],ina[N],reb[N],inb[N],ret[N],intt[N];
int i,len1,len2,lent,lenres,len;
int res[N>>1];
void Swap(double &x,double &y)
{double t = x; x = y; y = t;}
int rev(int x,int len)
{
    int ans = 0,i;
    fo(i,1,len) {ans<<=1; ans|=x&1; x>>=1;}
    return ans;
}
void FFT(double *reA,double *inA,int n,int flag)
{
    int s,i,j,k; int lgn = log((double)n) / log((double)2);
    fo(i,0,n-1)//数组重排
        {
            j = rev(i,lgn);
            if (j > i) {Swap(reA[i],reA[j]); Swap(inA[i],inA[j]);}
        }

    fo(s,1,lgn)
        {
            int m = (1 << s);
            double reWm = cos(2*pi/m) , inWm = sin(2*pi/m);
            if (flag) inWm = -inWm;
            for (k = 0;k < n; k += m)
                {
                    double reW = 1.0 , inW = 0.0;
                    fo(j,0,m/2-1)
                        {
                            int tag = k + j + m / 2;
                            double reT = reW * reA[tag] - inW * inA[tag];
                            double inT = reW * inA[tag] + inW * reA[tag];
                            double reU = reA[k+j] , inU = inA[k+j];
                            reA[k+j] = reU + reT; inA[k+j] = inU + inT;
                            reA[tag] = reU - reT; inA[tag] = inU - inT;
                            double reWt = reW * reWm - inW * inWm;
                            double inWt = reW * inWm + inW * reWm;
                            reW = reWt; inW = inWt;
                        }
                }

        }

}
void work()
{
    scanf(" %s %s",s1,s2);
        memset(res, 0 , sizeof(res)); 
        memset(rea, 0 , sizeof(rea));  
        memset(ina, 0 , sizeof(ina));  
        memset(reb, 0 , sizeof(reb));  
        memset(inb, 0 , sizeof(inb));  
    len1 = strlen(s1); len2 = strlen(s2);
    lent = (len1 > len2 ? len1 : len2); len = 1;
    while (len < lent) len <<= 1; len <<= 1;
    fo(i,0,len-1)
        {
            if (i < len1) rea[i] = (double) s1[len1-i-1] - '0';
            if (i < len2) reb[i] = (double) s2[len2-i-1] - '0';
            ina[i] = inb[i] = 0.0;
        }
    FFT(rea,ina,len,0); FFT(reb,inb,len,0);//求出a、b的点值表示法 
    fo(i,0,len-1)//求出c的点值表示法 
        {
            //printf("%.5lf %.5lf\n",rea[i],ina[i]);
            double rec = rea[i] * reb[i] - ina[i] * inb[i];
            double inc = rea[i] * inb[i] + ina[i] * reb[i];
            rea[i] = rec; ina[i] = inc;
        }
    FFT(rea,ina,len,1);
    fo(i,0,len-1) {rea[i] /= len; ina[i] /= len;}

    fo(i,0,len-1) res[i] = (int)(rea[i] + 0.5);
    fo(i,0,len-1) res[i+1] += res[i] / 10 , res[i] %= 10;

    lenres = len1 + len2 + 2;
    while (res[lenres] == 0 && lenres > 0) lenres--;
    fd(i,lenres,0) printf("%d",res[i]); printf("\n");
} 

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","w",stdout); 
    lon casenum;
    cin>>casenum;
    for(lon time=1;time<=casenum;++time)
    //for(;scanf("%d",&n)!=EOF;)
    {
        work();
        //cout<<mul(m1,m2)<<endl;
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/gaudar/p/9751570.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值