bzoj1876[SDOI2009] SuperGCD

题目链接:bzoj1876

题目大意:

就是求GCD。对于100%的数据,0 < A , B ≤ 10 ^ 10000。


题解:

高精度+更相减损术

更相减损术就是设有两个数A,B

首先判断A,B是否都是偶数,如果都是的话就一直除2,直到有某个数不是偶数为止。gcd(A,B)中2这个因子的个数就等于除2的次数。—— ①

做完这一步的A,B就肯定不会再有2的因子了。

所以如果A,B中有某个数是偶数,就不要大意的把它砍半直到为奇数。—— ②

当两个都是奇数的时候就相减一下,重复这两个步骤(②③)。 —— ③

========================================

这样的一道题做了我好久QAQ(%%更相减损术

TLE完了WA一年!讲真,拍了巨久!嗨呀好气啊


不过,好像还挺快的~

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define maxn 11000

const int mod=100000000;
struct node
{
	int a[1500],len;
	node(){len=1;memset(a,0,sizeof(a));}
}a,b;
char s[maxn];
void read(node &c)
{
	gets(s);
	int t,i,len,now=0;
	len=strlen(s);t=1;
	for (i=len-1;i>=0;i--)
	{
		now=now+(s[i]-'0')*t;t*=10;
		if ((len-i)%8==0) {c.a[c.len++]=now;now=0;t=1;}
	}
	if (now!=0) c.a[c.len++]=now;c.len--;
}
bool pz()
{
	if (a.len!=b.len) return false;
	int i;
	for (i=a.len;i>=1;i--)
	 if (a.a[i]!=b.a[i]) return false;
	return true;
}
bool comp()
{
	if (a.len>b.len) return true;
	else if (a.len<b.len) return false;
	int i;
	for (i=a.len;i>=1;i--)
	 if (a.a[i]>b.a[i]) return true;
	 else if (a.a[i]<b.a[i]) return false;
	return true;
}
void ct(node &c,node d)
{
	int i;
	for (i=1;i<=c.len;i++)
	{
		if (c.a[i]>=d.a[i]) c.a[i]-=d.a[i];
		else {c.a[i]=c.a[i]+mod-d.a[i];c.a[i+1]-=1;}
	}
	while (c.a[c.len]==0 && c.len>1) c.len--;
}
void diva()
{
	int i;
	for (i=a.len;i>=1;i--)
	{
		if (a.a[i]&1) a.a[i-1]+=mod;
		a.a[i]>>=1;
	}
	while (a.a[a.len]==0 && a.len>1) a.len--;
}
void divb()
{
	int i;
	for (i=b.len;i>=1;i--)
	{
		if (b.a[i]&1) b.a[i-1]+=mod;
		b.a[i]>>=1;
	}
	while (b.a[b.len]==0 && b.len>1) b.len--;
}
void multi()
{
	int i;
	for (i=a.len;i>=1;i--)
	{
		a.a[i]<<=1;
		if (a.a[i]>=mod) {a.a[i+1]++;a.a[i]-=mod;}
	}
	while (a.a[a.len+1]) a.len++;
}
void print()
{
	int i;
	printf("%d",a.a[a.len]);
	for (i=a.len-1;i>=1;i--)
	  printf("%08d",a.a[i]);
	printf("\n");
}
int main()
{
	int tot=0;read(a);read(b);
	while (!(a.a[1]&1) && !(b.a[1]&1)) {tot++;diva();divb();}
	while (!(a.a[1]&1)) diva();
	while (!(b.a[1]&1)) divb();
	while (!pz())
	{
		if (comp()) ct(a,b);
		else ct(b,a);
		while (!(a.a[1]&1)) diva();
		while (!(b.a[1]&1)) divb();
	}
	while (tot--) multi();
	print();
	return 0;
}


转载于:https://www.cnblogs.com/Euryale-Rose/p/6527810.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值