您的位置:首页 > 其它

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

2015-08-31 20:37 316 查看
剪辑地址: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: