ACM 二进制求最大公约数 HDU5050

<p style="font-family: 'Microsoft YaHei', 微软雅黑; color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">二进制GCD算法基本原理是:
 先用移位的方式对两个数除2,直到两个数不同时为偶数。然后将剩下的偶数(如果有的话)做同样的操作,这样做的原因是如果u和v中u为偶数,v为奇数,则有gcd(u,v)=gcd(u/2,v)。到这时,两个数都是奇数,将两个数相减(因为gcd(u,v) = gcd(u-v,v)),得到的是偶数t,对t也移位直到t为奇数。每次将最大的数用t替换。</p><p style="font-family: 'Microsoft YaHei', 微软雅黑; color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">
二进制GCD算法优点是只需用减法和二进制移位运算,不像Euclid's算法需要用除法,这在某些嵌入式系统中可能排上用场。</p>

#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
struct BigNum{
	int a[10100];
	int n;
	void input(char str[]){
		n = strlen(str);
		for(int i = 0;i < n;i++){
			a[i] = str[n-1-i]-'0';
//			printf("%c",a[i]);
		}
	}
	bool operator <(const BigNum &b)const{
		if(n < b.n)return true;
		if(n > b.n)return false;
		for(int i = n-1;i >= 0;i--){
			if(a[i] < b.a[i])return true;//妙哉!!结构体中转化b.a[i]
			if(a[i] > b.a[i])return false;
		}
		return true;
	}
	BigNum operator -(const BigNum &b)const{
		BigNum ret;
		ret.n = n;
		int mu = 0;//为了数位的变化
		for(int i = 0;i < n;i++){
			int tmp;
			if(i < b.n)tmp = a[i] - b.a[i] - mu;
			else tmp = a[i] - mu;
			if(tmp >= 0){
				mu = 0;
				ret.a[i] = tmp;
			}
			else {
				mu = 1;
				ret.a[i] = tmp+2;//二进制
			}
		}
		while(ret.n > 0 && ret.a[ret.n-1] == 0)ret.n--;//避免首位出现零
		return ret;
	}
	BigNum div2(){
		BigNum ret;
		ret.n = n-1;
		for(int i = 0;i < n-1;i++)
			ret.a[i] = a[i+1];
		return ret;
	}
	void output(){
		for(int i = n-1;i >= 0;i--)
			printf("%d",a[i]);
	}
};
//二进制的最大公约数只可能是0,1组合
void gcd(BigNum a,BigNum b){
	int c2 = 0;
	while(a.n && b.n){
		if(a.a[0]){
			if(b.a[0]){
				if(b < a)a = a-b;
				else b = b-a;
			}
			else b = b.div2();//移位运算
		}
		else {
			if(b.a[0])a = a.div2();
			else{
				a = a.div2();
				b = b.div2();
				c2++;
			}
		}
	}
	if(a.n)a.output();
	else b.output();
	while(c2--){
		printf("0");
	}
	printf("\n");
}
char str[10010];
BigNum a,b,c;

int main()
{
    //freopen("I.in","r",stdin);
    //freopen("I.out","w",stdout);
    int T;
	scanf("%d",&T);
	int iCase = 0;
	while(T--){
		iCase++;
		scanf("%s",str);//字符串输入注意
		a.input(str);
		scanf("%s",str);
		b.input(str);
		printf("Case #%d: ",iCase);
		gcd(a,b);
	}
    return 0;
}
  ------代码来自kuangbin
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值