SuperGCD,洛谷之提高历练地,数论(3-5)

前话

      数论就是研究整数的理论。包括公约公倍数、质数、欧拉定理和同余方程等。

正文

       其实数论不止那么简单

正文

      第一题:SuperGCD

      这一题就是很烦的代码加很烦的思路。

      GCD大家都想起了辗转相除法(gcd(a,b)=gcd(b,a%b));

      因为数据很大而且除运算和mod运算可能很浪费时间。所以推广辗转相减法:

      当两个数都为偶数时,gcd(a,b)=gcd(a/2,b/2)*2;

      当其中一个为偶数且另外一个不为偶数时,gcd(a,b)=gcd(a/2,b) (a mod 2 == 0) 

                                                                      gcd(a,b)=gcd(a,b/2) (b mod 2 == 0)

      否则,gcd(a,b)=gcd(b,a-b);

      没错,万恶的代码。(迭代万岁,递归超时哦!)

代码<deal>

#include<cstdio>
#include<cstdlib>
#include<cstring>

char s1[10010],s2[10010];
struct node{
	int s[10010];
	int l;
	friend node operator-(node a,const node&b){
		node t;
		t.l=a.l;
		for(int i=1;i<=t.l;i++){
			if(a.s[i]<b.s[i]){
				a.s[i]+=10;
				a.s[i+1]-=1;
			}
			t.s[i]=a.s[i]-b.s[i];
		}
		while(t.s[t.l]==0) t.l--;
		return t;
	}
	int compare(const node &b)const{
		if(l<b.l) return 0;
		if(l>b.l) return 1;
		for(int i=l;i>=1;i--){
			if(s[i]>b.s[i]) return 1;
			if(s[i]<b.s[i]) return 0;
		}
		return 1e9;
	}
	friend node operator/(const node&a,const int&x){
		int now=0;
		node t=a;
		for(int i=t.l;i>=1;i--){
			now*=10;
			now+=t.s[i];
			t.s[i]=now/x;
			now%=x;
		}
		while(t.s[t.l]==0) t.l--;
		return t;
	}
	friend node operator*(const node&a,const int&x){
		node t;
		t=a;
		t.s[t.l+1]=0;
		for(int i=1;i<=t.l;i++)
			t.s[i]*=x;
		for(int i=1;i<=t.l;i++){
			if(t.s[i]>9){
				t.s[i+1]+=t.s[i]/10;
				t.s[i]%=10;
				if(i==t.l) t.l++;
			}
		}
		return t;
	}
};
node a,b;

int main(){
	scanf("%s %s",s1,s2);
	a.l=strlen(s1),b.l=strlen(s2);
	for(int i=0;i<a.l;i++)
		a.s[a.l-i]=s1[i]-'0';
	for(int i=0;i<b.l;i++)
		b.s[b.l-i]=s2[i]-'0';
	int t=0;
	while(a.s[1]%2==0 && b.s[1]%2==0) {
		t++;
		a=a/2;
		b=b/2;
	}
	while(a.compare(b)!=1e9){
		if(a.compare(b)==1) a=a-b;else b=b-a;
		while(a.s[1]%2==0) a=a/2;
		while(b.s[1]%2==0) b=b/2;
	}
	for(int i=1;i<=t;i++)
		a=a*2;
	for(int i=a.l;i>=1;i--)
		printf("%d",a.s[i]);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值