zoukankan      html  css  js  c++  java
  • 洛谷 2152 [SDOI2009]SuperGCD

    Description

    Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你决定写一个程序来教训他。

    Input

    共两行: 第一行:一个数A。 第二行:一个数B。

    Output

    一行,表示A和B的最大公约数。

    Sample

    输入样例#1:
    12
    54
    输出样例#1:
    6

    Hints

    对于20%的数据,0 < A , B ≤ 10 ^ 18。

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



    我的数学可能要完了,我看完数据范围以后想算一下如果用辗转相除的话能不能过
    我发现我不会算,可是不会其他算gcd的方法了诶
    看到题解,发现大家都用了gcd和疑似gcd的方法
    我又尝试算了一下复杂度,这个时候我打开了计算器,可是太大了,会溢出......
    然后恍然大悟ToT
    Solution
    可以写辗转相除,但是我不想写高精取模,但是有一个叫Stein的方法

          [1]. 若 aa 为奇数,bb 为偶数,GCD(a, b) = GCD(a, b / 2)GCD(a,b)=GCD(a,b/2)

               表示 bb 存在2这个因子而 aa 不存在,则将 bb 除以2,,不考虑因子2;

          [2]. 若 aa 为偶数,bb 为奇数,GCD(a, b) = GCD(a / 2, b)GCD(a,b)=GCD(a/2,b)

               表示 aa 存在2这个因子而 bb 不存在,则将 aa 除以2,不考虑因子2;

          [3]. 若 aa 为偶数,bb 为偶数,GCD(a, b) = GCD(a / 2, b / 2)GCD(a,b)=GCD(a/2,b/2)

               表示 a, ba,b 都存在2这个因子,则 GCD(a, b)GCD(a,b) 也存在因子2,则将当前答案乘以2,a, ba,b 都除以2;

          [4]. 若 aa 为奇数,bb 为奇数,GCD(a, b) = GCD(a - b, b) (a > b)GCD(a,b)=GCD(ab,b)(a>b)

    因为位数太多,所以要压位,因为只有*2,/2,-的操作,所以可以多压一点

    De了很久的bug

    一开始写的是递归版的gcd,暴栈了,递归到某一个函数里时,就会RE

    后来发现输入有问题,不能用getline,会读空格进来,cin是不读空格的

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<string>
    using namespace std;
    const int w=1000000000,wi=9;
    struct big{
    	int a[2001];
    	int len;
    	big(){memset(a,0,sizeof(a));len=0;}
    	big(string x){        //初始化的时候赋值需要找big(string) 
    		*this = x;
    	}
    	bool operator <(const big&v){
    		if(len!=v.len)
    		  return len<v.len;
    		for(int i=len;i>=1;i--)
    		  if(a[i]!=v.a[i])
    		    return a[i]<v.a[i];
    		return 0;
    	}
    	big& operator =(string v){
    		len=0;int lv=v.length();
    		for(int i=lv-1;i>=0;i-=wi)
    		{
    			int val=0;
    			for(int j=max(i-wi+1,0);j<=i;j++)
    			  val=val*10+v[j]-'0';      //v[j]写成了j 
    			a[++len]=val;
    		}
    		return *this;
    	}
    	big& operator =(big&v){
    		len=max(len,v.len);        //取max,因为要把本来有的但是赋值以后没有的位变成0 
    		for(int i=1;i<=len;i++)
    		  a[i]=v.a[i];
    		while(len&&!a[len]) --len; 
    		return *this;
    	}
    	big& operator -(big&v){
    		big res;
    		res.len=len;
    		for(int i=1;i<=len;i++)
    		{
    			res.a[i]+=a[i]-v.a[i];
    			if(res.a[i]<0)
    			{
    				res.a[i]+=w;
    				res.a[i+1]--;
    			}
    		}
    		while(res.len&&!res.a[res.len]) --res.len;        //res.len不为负
    		return res;
    	}
    	big& operator /(int v){
    		big res;
    		res.len=len;
    		for(int i=len;i>=1;i--)
    		{
    			res.a[i]=a[i]/v;
    		    a[i-1]+=(a[i]-v*res.a[i])*w;
    		}
    		while(res.len&&!res.a[res.len]) --res.len;
    		return res;
    	}
    	big& operator *(int v){
    		big res;
    		res.len=len+1;
    		for(int i=1;i<=len;i++)
    		{
    			res.a[i]+=a[i]*2;
    			res.a[i+1]+=res.a[i]/w;
    			res.a[i]=res.a[i]%w;
    		}
    		while(res.len&&!res.a[res.len]) --res.len;
    		return res;
    	}
    };
    int read()
    {
    	int ans=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
    	return ans*f;
    }
    big mid;int mi=0;
    big gcd(big a,big b)
    {
    	while(b.len)
    	{
    		if(a<b)
    		{
    			mid=a;a=b;b=mid;
    		}
    		if(!b.len)
    	  	  return a;
    		if(a.a[1]&1&&b.a[1]&1)
    		{
    			mid=b;
    		    b=a-b;
    		    a=mid;
    		}
    		else if(a.a[1]&1)
    		{
    			b=b/2;
    		}
    		else if(b.a[1]&1)
    		{
    			a=a/2;
    		}
    		else
    		{
    			a=a/2;b=b/2;mi++;
    		}
    	}
    	for(int i=1;i<=mi;i++)
    	  a=a*2;
    	return a;
    }
    int main()
    {
    //	freopen("o.txt","r",stdin);
    //	freopen("oo.out","w",stdout);
    	string a,b;
    	cin>>a>>b;       //不能用cin要读空格
    	big a1,b1;
    	a1=a;b1=b;
    	big ans=gcd(a1,b1);
    	for(int i=ans.len;i>=1;i--)
    	  if(i==ans.len)
    	    printf("%d",ans.a[i]);
    	  else
    	    printf("%09d",ans.a[i]);
    	return 0;
    }
    /*
    111111111111111
    111111111111110
    */
  • 相关阅读:
    工厂模式
    dubbo
    WebSocket WebService
    消息中间
    原型模式
    ApiPost Apifox
    Future 的使用与源码解析
    JUC 线程池的使用与源码解析
    ReentrantLock 源码解析
    CountDownLatch 的使用与源码解析
  • 原文地址:https://www.cnblogs.com/charlotte-o/p/7630012.html
Copyright © 2011-2022 走看看