高精度计算:最大公约数【两个数字字符串】
剪辑地址: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; }