bzoj千题计划288:bzoj1876: [SDOI2009]SuperGCD

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj千题计划288:bzoj1876: [SDOI2009]SuperGCD相关的知识,希望对你有一定的参考价值。

http://www.lydsy.com/JudgeOnline/problem.php?id=1876

 

高精压位GCD

 

对于  GCD(a, b)  a>b

 

若 a 为奇数,b 为偶数,GCD(a, b) = GCD(a, b / 2)

 

若 a 为偶数,b 为奇数,GCD(a, b) = GCD(a / 2, b)

 

若 a 为偶数,b 为偶数,GCD(a, b) = 2*GCD(a / 2, b / 2)

若 a 为奇数,b 为奇数,GCD(a, b) = GCD(a - b, b)

 

 

vector 压8位 是 压4位 用时的一半

vector 写 高精 真心 方便

 

 

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

#define N 100000000

typedef vector<int> bignum;

inline bignum read()
{
    bignum a;
    string s,ss;
    cin>>s;
    reverse(s.begin(),s.end());
    while(s.size()>8)
    {
        ss=s.substr(0,8);
        a.push_back(ss[0]+ss[1]*10+ss[2]*100+ss[3]*1000+ss[4]*10000+ss[5]*100000+ss[6]*1000000+ss[7]*10000000-48*11111111);
        s=s.substr(8,s.size());
    }
    int b=0;
    reverse(s.begin(),s.end());
    for(int i=0;i<s.size();++i) b=b*10+s[i]-48;
    a.push_back(b);
    return a;
}

inline bool bigger(bignum a,bignum b)
{
    if(a.size()>b.size()) return true;
    if(a.size()<b.size()) return false;
    for(int i=a.size()-1;i>=0;--i) 
    {
        if(a[i]>b[i]) return true;
        if(a[i]<b[i]) return false;
    }
    return false;
}

inline bool iseven(bignum a)
{
    return !(*a.begin()&1);
}

inline bool iszero(bignum a)
{
    return a.size()==1 && !(*a.begin());
}

inline void delzero(bignum &a)
{
    while(a.size()>1)
    {
        bignum::iterator it=--a.end();
        if(*it) break;
        a.erase(it);
    }
}

inline void sub(bignum &a,bignum b)
{
    int i;
    for(i=0;i<b.size();++i)
    {
        if(a[i]<b[i]) a[i+1]--,a[i]+=N;
        a[i]-=b[i];
    }
    while(i<a.size() && a[i]<0)
    {
        a[i]+=N;
        ++i;
        --a[i];
    }
    delzero(a);
}

inline void half(bignum &a)
{
    for(int i=a.size()-1;i>=0;--i)
    {
        if(a[i]&1) a[i-1]+=N;
        a[i]=a[i]>>1;
    }
    delzero(a);    
}

inline void doubled(bignum &a)
{
    for(int i=0;i<a.size();++i)
    {
        a[i]<<=1;
        if(i>0 && a[i-1]>=N) a[i-1]-=N,a[i]++;
    }
    bignum::iterator it=--a.end();
    if(*it>=N) *it-=N,a.push_back(1);
}

inline void output(bignum a)
{
    int i=a.size()-1;
    printf("%d",a[i]);
    if(!i) return;
    for(--i;i>=0;--i) printf("%08d",a[i]);
}

int main()
{
    bignum a=read(),b=read();
    int c=0;
    while(1)
    {
        if(bigger(b,a)) swap(a,b);
        if(iszero(b)) break;
        if(iseven(a) && iseven(b))
        {
            half(a); half(b);
            c++;
        }
        else if(iseven(a)) half(a);
        else if(iseven(b)) half(b);
        else sub(a,b);
        
    }
    while(c--) doubled(a);
    output(a);
    return 0;
}        

 

以上是关于bzoj千题计划288:bzoj1876: [SDOI2009]SuperGCD的主要内容,如果未能解决你的问题,请参考以下文章

bzoj千题计划197:bzoj4247: 挂饰

bzoj千题计划118:bzoj1028: [JSOI2007]麻将

bzoj千题计划165:bzoj5127: 数据校验

bzoj千题计划144:bzoj1176: [Balkan2007]Mokia

bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

bzoj千题计划142:bzoj3144: [Hnoi2013]切糕