高精度计算:最大公约数【两个数字字符串】

剪辑地址:http://hzwer.com/3023.html

 

计算两个超级大数的最大公约数:

样例:

111111111111111111111

22222222222222222222222222222

输出:

我也不知道~~~

 

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 1000000000
using namespace std;
char ch1[10005],ch2[10005];
int la,lb,cnt;
struct data{int a[1205],l;}a,b;
bool com()
{
	if(a.l<b.l)return 0;
	if(a.l>b.l)return 1;
	for(int i=a.l;i>0;--i)
	    if(a.a[i]>b.a[i])return 1;
	    else if(a.a[i]<b.a[i])return 0;
	return 1;
}
void print(data a)
{
    while(a.a[a.l]==0)a.l--;
	for(int i=a.l;i>0;--i)
	    if(i==a.l)printf("%d",a.a[i]);
	    else printf("%09d",a.a[i]);
}
inline data sub(data a,data b)
{
	int k;
    data c;
	for(int i=1;i<=1200;++i)
	{
	   if(i<=b.l)c.a[i]=a.a[i]-b.a[i];
	   else if(i<=a.l)c.a[i]=a.a[i];
	   else c.a[i]=0;
	   if(c.a[i]<0)
	   {
	      c.a[i]+=inf;
	      a.a[i+1]--;
	   }
    }
    c.l=a.l;
    while(c.a[c.l]==0&&c.l)c.l--;
    return c;
}
void diva()
{
	for(int i=1;i<=a.l;i++)
	{
	    if(a.a[i]&1)a.a[i-1]+=inf/2;
	    a.a[i]>>=1;
	}
	if(!a.a[a.l])a.l--;
}
void divb()
{
    for(int i=1;i<=b.l;i++)
	{
	    if(b.a[i]&1)b.a[i-1]+=inf/2;
	    b.a[i]>>=1;
	}
	if(!b.a[b.l])b.l--;
}
void mul()
{
	for(int i=a.l;i>0;i--)
	{
	   a.a[i]<<=1;
	   a.a[i+1]+=a.a[i]/inf;
	   a.a[i]%=inf;
    }
    while(a.a[a.l]>0)a.l++;
    for(int i=b.l;i>0;i--)
	{
	   b.a[i]<<=1;
	   b.a[i+1]+=b.a[i]/inf;
	   b.a[i]%=inf;
    }
    while(b.a[b.l]>0)b.l++;
}
int main()
{
	scanf("%s%s",ch1+1,ch2+1);
	la=strlen(ch1+1);lb=strlen(ch2+1);
	if(la%9)a.l=la/9+1;
	else a.l=la/9;
	if(lb%9)b.l=lb/9+1;
	else b.l=lb/9;
	for(int i=1;i<=a.l;++i)
	{
		int k1=max(1,la-i*9+1),k2=la-(i-1)*9;
		for(int j=k1;j<=k2;++j)
		    a.a[i]=a.a[i]*10+ch1[j]-'0';
	}
	for(int i=1;i<=b.l;++i)
	{
		int k1=max(1,lb-i*9+1),k2=lb-(i-1)*9;
		for(int j=k1;j<=k2;++j)
		    b.a[i]=b.a[i]*10+ch2[j]-'0';
	}
	while(1)
    {
    	if((a.a[1]%2==0)&&(b.a[1]%2==0)){diva();divb();cnt++;}
    	else if((a.a[1]%2==0))diva();
    	else if((b.a[1]%2==0))divb();
	    if(com()){a=sub(a,b);if(!a.l){while(cnt--)mul();print(b);break;}}
	    else {b=sub(b,a);if(!b.l){while(cnt--)mul();print(a);break;}}
    }
	return 0;
}

 

2. 计算一个大数与int类型数字的最大公约数  【注意: C/C++里面数组名做参数传递进去的是数组的地址, 会发生值改变,如果原数组还有用,请先备份到另一个数组】

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//计算一个大数与一个int型整数的最大公约数模板

int gcd2(int a, int b)
{
    return b==0?a:gcd2(b, a%b);
}
int gcd(int *a, int len, int b){
    int yu;//保存大数对b取余后的余数
    int i, jin=0;//数组存储在0--(len-1)
    int cur;
    for(i=0; i<len; i++){
        cur=(a[i]+jin*10)%b;
        jin=cur;
    }
    if(jin==0){//说明可以整除 则最大公约数是b
        return b;
        //也可以计算输出商
    }
    else{//再计算(大数a%b)与b的最大公约数
        return gcd2(jin, b);
    }
}

int main()
{
    char a[1001]; int b;
    int aa[1001];

    while(scanf("%s %d", a, &b)!=EOF)
    {
        //将字符串转换成数字串
        int len=strlen(a);
        for(int i=0; i<len; i++){
            aa[i]=a[i]-48;
        }
        printf("%d\n", gcd(aa, len, b));
    }
    return 0;
}

 3.  HDU 4276 Cut the Cake (用上面的模板实现)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4762

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int m, n;

int gcd2(int a, int b)
{
    return b==0?a:gcd2(b, a%b);
}
int gcd(int *a, int len, int b){
    int yu;//保存大数对b取余后的余数
    int i, jin=0;//数组存储在0--(len-1)
    int cur;
    for(i=0; i<len; i++){
        cur=(a[i]+jin*10)%b;
        jin=cur;
    }
    if(jin==0){//说明可以整除 则最大公约数是b
        return b;
        //也可以计算输出商
    }
    else{//再计算(大数a%b)与b的最大公约数
        return gcd2(jin, b);
    }
}

int main()
{
    int a[201];
    int tg; scanf("%d", &tg);
    while(tg--)
    {
        scanf("%d %d", &m, &n);
        int head=200;
        memset(a, 0, sizeof(a));
        int jin, cur;
        a[head]=m;  //累乘计算 m^(n-1)
        for(int i=1; i<=n-2; i++){
            for(int j=200; j>=head; j--){
                a[j]=a[j]*m;
            }
            jin=0;
            for(int j=200; j>=head; j--){
                cur=(a[j]+jin)%10;
                jin=(a[j]+jin)/10;
                a[j]=cur;
            }
            if(jin>0){
                head--; a[head]=jin;
            }
        }
        int b[201];
        for(int i=0; i<=200; i++)
            b[i]=a[i];

        int g=gcd( a+head, 200-head+1, n);
       // printf("gcd = %d\n", g);
        printf("%d%c", n/g, '/');
        jin=0;
        for(int i=head; i<=200; i++){
            cur=(b[i]+jin*10)%g;
            b[i]=(b[i]+jin*10)/g;
            jin=cur;
        }
        while(b[head]==0 && head<=200) head++;
        for(int i=head; i<=200; i++)
            printf("%d", b[i]);
        printf("\n");
    }
    return 0;
}

 

posted @ 2015-08-31 20:37  我喜欢旅行  阅读(1208)  评论(0编辑  收藏  举报