GVKun编程网logo

【FFT】大数乘法 hdu1402(汇编大数乘法)

3

对于想了解【FFT】大数乘法hdu1402的读者,本文将提供新的信息,我们将详细介绍汇编大数乘法,并且为您提供关于2012蓝桥杯【初赛试题】大数乘法、51nod1027大数乘法、Hdu1402A*BP

对于想了解【FFT】大数乘法 hdu1402的读者,本文将提供新的信息,我们将详细介绍汇编大数乘法,并且为您提供关于2012 蓝桥杯【初赛试题】大数乘法、51nod 1027 大数乘法、<模板> Hdu 1402 A * B Problem Plus 大数乘法、BZOJ2179: FFT快速傅立叶 & caioj1450:【快速傅里叶变换】大整数乘法的有价值信息。

本文目录一览:

【FFT】大数乘法 hdu1402(汇编大数乘法)

【FFT】大数乘法 hdu1402(汇编大数乘法)

存一波 FFT 大数乘法 模板 :

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const double PI = acos(-1.0);
//复数结构体
struct Complex
{
    double r,i;
    Complex(double _r=0.0,double _i=0.0)
    {
        r = _r; i = _i;
    }
    Complex operator +(const Complex &b)
    {
        return Complex(r+b.r,i+b.i);
    }
    Complex operator -(const Complex &b)
    {
        return Complex(r-b.r,i-b.i);
    }
    Complex operator *(const Complex &b)
    {
        return Complex(r*b.r-i*b.i,r*b.i+i*b.r);
    }
};
/*
 * 进行FFT和IFFT前的反转变换。
 * 位置i和 (i二进制反转后位置)互换
 * len必须去2的幂
 */
void change(Complex y[],int len)
{
    int i=1,j=len/2,k;
    for(;i<len-1;i++){
        if(i<j)
            swap(y[i],y[j]);

        k=len/2;
        while(j>=k){
            j-=k;
            k/=2;
        }
        if(j<k)
            j+=k;
    }
}
/*
 * 做FFT
 * len必须为2^k形式,
 * on==1时是DFT,on==-1时是IDFT
 */
void fft(Complex y[],int len,int on)
{
    change(y,len);
    for(int h=2;h<=len;h<<= 1)
    {
        Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
        for(int j=0;j<len;j+=h)
        {
            Complex w(1,0);
            for(int k=j;k<j+h/2;k++){
                Complex u=y[k];
                Complex t=w*y[k+h/2];
                y[k]=u+t;
                y[k+h/2]=u-t;
                w=w*wn;
            }
        }
    }

    if(on==-1)
        for(int i=0;i<len;i++)
            y[i].r/=len;
}

const int MAXN=100010<<2;
Complex x1[MAXN],x2[MAXN];
char str1[MAXN/2],str2[MAXN/2];
int sum[MAXN];

int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%s%s",str1,str2)==2)
    {
        int len1=strlen(str1);
        int len2=strlen(str2);
        int len=1;
        while(len<len1*2 || len<len2*2)
            len<<=1;
        for(int i=0;i<len1;i++)
            x1[i]=Complex(str1[len1-1-i]-''0'',0);
        for(int i=len1;i<len;i++)
            x1[i]=Complex(0,0);
        for(int i=0;i<len2;i++)
            x2[i]=Complex(str2[len2-1-i]-''0'',0);
        for(int i=len2;i<len;i++)
            x2[i]=Complex(0,0);
        //求DFT
        fft(x1,len,1);
        fft(x2,1);
        for(int i=0;i<len;i++)
            x1[i]=x1[i]*x2[i];
        fft(x1,-1);
        for(int i=0;i<len;i++)
            sum[i]=(int)(x1[i].r+0.5);///注意精度
        ///-----------结束-----------//
        for(int i=0;i<len;i++){
            sum[i+1]+=sum[i]/10;
            sum[i]%=10;
        }
        len=len1+len2-1;
        while(sum[len]<=0&&len>0)
            len--;
        for(int i=len;i>=0;i--)
            printf("%c",sum[i]+''0'');
        printf("\n");
    }
    return 0;
}

2012 蓝桥杯【初赛试题】大数乘法

2012 蓝桥杯【初赛试题】大数乘法

大数乘法

对于32位字长的机器,大约超过20亿,用int类型就无法表示了,我们可以选择int64类型,但无论怎样扩展,固定的整数类型总是有表达的极限!如果对超级大整数进行精确运算呢?一个简单的办法是:仅仅使用现有类型,但是把大整数的运算化解为若干小整数的运算,即所谓:“分块法”。

如图【1.jpg】表示了分块乘法的原理。可以把大数分成多段(此处为2段)小数,然后用小数的多次运算组合表示一个大数。可以根据int的承载能力规定小块的大小,比如要把int分成2段,则小块可取10000为上限值。注意,小块在进行纵向累加后,需要进行进位校正。

以下代码示意了分块乘法的原理(乘数、被乘数都分为2段)。

 

#include <stdio.h>

#include <iostream>

using namespace std;

 

void bigmul(int x,int y,int r[])

{

    int base = 10000;

    int x2 = x / base;

    int x1 = x % base;

    int y2 = y / base;

    int y1 = y % base;

 

    int n1 = x1 * y1;

    int n2 = x1 * y2;

    int n3 = x2 * y1;

    int n4 = x2 * y2;

 

    r[3] = n1 % base;

    r[2] = n1 / base + n2 % base + n3 % base;

    --------------- // 填空

    r[0] = n4 / base;

 

     ---------------  //填空

    r[2] = r[2] % base;

    r[0] += r[1] / base;

    r[1] = r[1] % base;

}

int main(int argc,char* argv[])

{

    int x[] = {0,0};

    bigmul(87654321,12345678,x);

    printf("%d%d%d%d\n",x[0],x[1],x[2],x[3]);

    system("pause");

    return 0;

}

 

 

 

解题思路:

不算难,就是类似平时乘法运算中的进位

按照它的算法,99*99应该是这个样子

 

99*99正常方法:

 99

x99

---------

  891

891

---------

9801

 

99*99用题中叙述的方法:

 99

x99

---------

       81

    81

    81

 81

---------

 9  8  0 1

 

假设9为r[0],8、0、1分别是r[1]、r[2]、r[3],四个81分别是n1,n2、n3、n4。

则r[3]=n1%10;

r[2]=n1/10+n2%10+n3%10;

r[1]=n4%10+n2/10+n3/10;

r[0]=n4/10;

得到了上面的一组结果,很容易就推出了空格1,空格二就是简单的进位加减了,嘿嘿,分值到手!

 

#include <stdio.h>
#include <iostream>
using namespace std;

void bigmul(int x,int r[])
{
    int base = 10000;
    int x2 = x / base;
    int x1 = x % base;
    int y2 = y / base;
    int y1 = y % base;

    int n1 = x1 * y1;
    int n2 = x1 * y2;
    int n3 = x2 * y1;
    int n4 = x2 * y2;

    r[3] = n1 % base;//取最后一位 
    r[2] = n1 / base + n2 % base + n3 % base;//取倒数第二位(n1的首和n2、n3的尾相加) 
    r[1] = n2 / base + n3 / base + n4 % base; //取倒数第三位(n2、n3的首与n4的尾相加) 
    r[0] = n4 / base;//取n4的首 

    r[1] += r[2] / base;  // r[1]要加上后面进位的数 
    r[2] = r[2] % base;//只取进位后的余数 
    r[0] += r[1] / base;//r[0]要加上后面进位的数 
    r[1] = r[1] % base;//只取进位后的余数 
    //r[3]没有做任何加减,所以不需要进位也不需要加任何一位进的位数 
}
int main(int argc,char* argv[])
{
    int x[] = {0,0};
    bigmul(87654321,x);
    printf("%d%d%d%d\n",x[3]);
    system("pause");
    return 0;
}

51nod 1027 大数乘法

51nod 1027 大数乘法

51nod 1027 大数乘法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define E 2.71828
#define MOD 10007
#define N 1100

int a1[N],a2[N],aresult[2*N];
char str1[N],str2[N];
int main()
{
    memset(aresult,0,sizeof(aresult));
    memset(a1,sizeof(a1));
    scanf("%s",str1);
    int len1=strlen(str1);
    int j = 0;
    for(int i=len1-1;i>=0;i--)
        a1[j++]=str1[i]-''0'';
    scanf("%s",str2);
    memset(a2,sizeof(a2));
    int len2=strlen(str2);
    j = 0;
    for(int i=len2-1;i>=0;i--)
        a2[j++]=str2[i]-''0'';
    for(int i=0;i<len1;i++)
        for(j=0;j<len2;j++)
            aresult[i+j]+=a1[i]*a2[j];
    for(int i=0;i<(N-10)*2;i++)
    {
        if(aresult[i]>=10)
        {
            aresult[i+1] += aresult[i]/10;
            aresult[i] %= 10;
        }
    }
    int pan_0 = 0;
    for(int i=(N-10)*2;i>=0;i--)
    {
        if(pan_0)
            printf("%d",aresult[i]);
        else if(aresult[i])
        {
            printf("%d",aresult[i]);
            pan_0 = 1;
        }
    }
    printf("\n");
    return 0;
}

<模板> Hdu 1402 A * B Problem Plus 大数乘法

<模板> Hdu 1402 A * B Problem Plus 大数乘法

A * B Problem Plus

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12315    Accepted Submission(s): 2157


Problem Description
Calculate A * B.
 

Input
Each line will contain two integers A and B. Process to end of file.

Note: the length of each integer will not exceed 50000.
 

Output
For each case,output A * B in one line.
 

Sample Input
  
  
1 2 1000 2
 

Sample Output
  
  
2 2000
 

虽然还是没有AC。超时了。未解之谜,仔细再看看。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
#define LL __int64
#define M 10000000000
using namespace std;
LL a[5100],b[5100],c[110000];
char s1[500010],s2[500010];
void MUL()
{
	int t,i,j;
	memset(c,sizeof(c));
	for (i=a[0];i>0;i--)
	{
		t=a[0]-i+1;
		for (j=b[0];j>0;j--)
		{
			c[t+b[0]-j+1]+=a[i]*b[j] / M;
			c[t+b[0]-j]+=a[i]*b[j]%M;
		}
		if (c[t+1])
			c[0]=t+1;
		else c[0]=t;
	}
}
int main()
{
	while (gets(s1))
	{
		gets(s2);
		strrev(s1);
		strrev(s2);
		int l1=strlen(s1)-1;
		int l2=strlen(s2)-1;
		memset(a,sizeof(0));
		memset(b,sizeof(0));
		while(l1>=0)
		{
			LL k=0,s=0;
			while (k<10 && l1>=0)
			{
				s=s*10+s1[l1]-''0'';
				k++;
				l1--;
			}
			a[0]++;
			a[a[0]]=s;
		}
		while(l2>=0)
		{
			int k=0,s=0;
			while (k<10 && l2>=0)
			{
				s=s*10+s2[l2]-''0'';
				k++;
				l2--;
			}
			b[0]++;
			b[b[0]]=s;
		}
		MUL();
		printf("%I64d",c[c[0]]);
		for (int i=c[0]-1;i>1;i--)
			printf("%010I64d",c[i]);
		printf("%I64d\n",c[1]);
		//cout<<endl;
	}
	return 0;
}

BZOJ2179: FFT快速傅立叶 & caioj1450:【快速傅里叶变换】大整数乘法

BZOJ2179: FFT快速傅立叶 & caioj1450:【快速傅里叶变换】大整数乘法

【传送门:BZOJ2179&caioj1450】


简要题意:

  给出两个超级大的整数,求出a*b


题解:

  Rose_max出的一道FFT例题,卡掉高精度 = =(没想到BZOJ也有)

  只要把a和b的每一位当作是多项式的系数,然后做FFT就好了

  然后将答案取下来,进行进位的操作,最后输出就好了


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const double PI=acos(-1.0);
struct Complex
{
    double r,i;
    Complex(){}
    Complex(double _r,double _i){r=_r;i=_i;}
    friend Complex operator + (const Complex &x,const Complex &y){return Complex(x.r+y.r,x.i+y.i);}
    friend Complex operator - (const Complex &x,const Complex &y){return Complex(x.r-y.r,x.i-y.i);}
    friend Complex operator * (const Complex &x,const Complex &y){return Complex(x.r*y.r-x.i*y.i,x.i*y.r+x.r*y.i);}
}a[410000],b[410000];
int n,m;
int R[410000];
void fft(Complex *y,int len,int on)
{
    for(int i=0;i<len;i++) if(i<R[i]) swap(y[i],y[R[i]]);
    for(int i=1;i<len;i<<=1)
    {
        Complex wn(cos(PI/i),sin(on*PI/i));
        for(int j=0;j<len;j+=(i<<1))
        {
            Complex w(1,0);
            for(int k=0;k<i;k++,w=w*wn)
            {
                Complex u=y[j+k];
                Complex v=w*y[j+k+i];
                y[j+k]=u+v;
                y[j+k+i]=u-v;
            }
        }
    }
    if(on==-1) for(int i=0;i<len;i++) y[i].r/=len;
}
void calc()
{
    m+=n;
    int L=0;
    for(n=1;n<=m;n<<=1) L++;
    for(int i=0;i<n;i++) R[i]=(R[i>>1]>>1)|(i&1)<<(L-1);
    fft(a,n,1);
    fft(b,n,1);
    for(int i=0;i<=n;i++) a[i]=a[i]*b[i];
    fft(a,n,-1);
}
char st[110000];
int d[410000];
int main()
{
    scanf("%s",st+1);
    n=strlen(st+1);n--;
    for(int i=0;i<=n;i++) a[i].r=double(st[i+1]-''0'');
    scanf("%s",st+1);
    m=strlen(st+1);m--;
    for(int i=0;i<=m;i++) b[i].r=double(st[i+1]-''0'');
    calc();
    for(int i=0;i<=m;i++) d[i]=int(a[m-i].r+0.5);
    for(int i=0;i<=m;i++)
    {
        d[i+1]+=d[i]/10;
        d[i]%=10;
    }
    int i=m;
    while(d[i+1]!=0)
    {
        i++;
        d[i+1]+=d[i]/10;
        d[i]%=10;
    }
    m=i;
    for(int i=m;i>=0;i--) printf("%d",d[i]);
    printf("\n");
    return 0;
}

关于【FFT】大数乘法 hdu1402汇编大数乘法的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于2012 蓝桥杯【初赛试题】大数乘法、51nod 1027 大数乘法、<模板> Hdu 1402 A * B Problem Plus 大数乘法、BZOJ2179: FFT快速傅立叶 & caioj1450:【快速傅里叶变换】大整数乘法等相关知识的信息别忘了在本站进行查找喔。

本文标签:

上一篇Transwarp Pilot: 让BI分析全面自助化

下一篇干货丨一文了解面向流程的大数据处理框架NiFi(做大数据必须了解的多种处理框架)