【题解】 P2152 [SDOI2009]SuperGCD

\(Description:\)

写高精的\(gcd(a,b)\)

\(Sample\) \(Input\):

12
54

\(Sample\) \(Output\)

6

题意简介明了,然而代码。。。很长。。。。。。。。。。。。

一开始单纯的以为可以直接高精过,用更相减损术做gcd,结果wei大了。

敲了一个压了八位的高精,又wei了。

我开始思考。。。

事实证明我得写正解?

(事实是我重载小于号时是从前往后判的。。。。。

但是无知的我开始看题解:

对于更相减损术的优化:

  • a是偶数,b是偶数 那么\(gcd(a,b)=gcd(a/2,b/2)*2\)

  • a是偶数,b是奇数 那么\(gcd(a,b)=gcd(a /2,b)\)

  • a是奇数,b是偶数 那么\(gcd(a,b)=gcd(a,b/2)\)

证明:(我喜欢口糊,大量文字注意!!!

  • 1->显然
  • 2->显然
  • 3->显然

大量文字。。。。。。

其实都挺好理解的,那么知道了这三条性质,就可以优化了

时间复杂度

\(O(我不知道)\)

这是什么神仙复杂度。。。。。。

附上写了一个晚上的高精。。。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=100000,B=100000000,MAXM=3000;
int A[MAXN+5];
namespace Huge_int {
    using namespace std;
    struct huge_int {
        int n;
        int a[MAXM+5];
        inline void clear() { memset(a,0,sizeof(a));n=0; }
        inline void work() { while(n>1 && !a[n]) n--; }
        inline huge_int rd() {
            memset(A,0,sizeof(A));
            clear();
            char ch=getchar();
            while(ch<'0' || ch>'9') ch=getchar();
            while(ch<='9' && ch>='0') A[++n]=ch-'0',ch=getchar();
            for(int i=1;i+i<=n;++i) swap(A[i],A[n-i+1]);
            for(int i=1;i<=n;i+=8){
                int j=(i+7)/8;
                a[j]=(A[i]+A[i+1]*10+A[i+2]*100+A[i+3]*1000+A[i+4]*10000+A[i+5]*100000+A[i+6]*1000000+A[i+7]*10000000);
            }
            n=(n+7)/8;
            return *this;
        }
        inline huge_int wrt() const {
            printf("%lld",a[n]);
            for(int i=n-1;i>=1;--i) printf("%08lld",a[i]);
            putchar('\n');
            return *this;
        }
        inline bool operator < (const huge_int &nt) const {
            if(n<nt.n) return 1;
            if(n>nt.n) return 0;
            for(int i=n;i>=1;--i)
                if(a[i]!=nt.a[i])return a[i]<nt.a[i];
            return 0;
        }
        inline bool operator > (const huge_int &nt) const {
            return nt<*this;
        }
        inline bool operator != (const huge_int &nt) const {
            return (*this<nt) || (nt<*this);
        }
        inline bool operator == (const huge_int &nt) const {
            return !(*this!=nt);
        }
        inline huge_int operator = (const int &nt) {
            n=0;
            int x=nt;
            while(x){
                a[++n]=x%B;
                x/=B;
            }
            return *this;
        }
        inline huge_int operator + (const huge_int &nt) const {
            huge_int tmp;
            tmp.clear();
            tmp.n=max(n,nt.n)+1;
            for(int i=1;i<=tmp.n;++i){
                tmp.a[i]+=a[i]+nt.a[i];
                tmp.a[i+1]+=tmp.a[i]/B;
                tmp.a[i]%=B;
            }
            tmp.work();
            return tmp;
        }
        inline huge_int operator - (const huge_int &nt) const {
            huge_int tmp;
            tmp.clear();
            int x=0;
            tmp.n=n;
            for(int i=1;i<=tmp.n;++i){
                x+=a[i]-nt.a[i];
                if(x<0) tmp.a[i]=x+B,x=-1;
                else tmp.a[i]=x,x=0;
            }
            tmp.work();
            return tmp;
        }
        inline huge_int operator * (const huge_int &nt) const {
            huge_int tmp;
            tmp.clear();
            tmp.n=n+nt.n;
            for(int i=1;i<=n;++i)
                for(int j=1;j<=nt.n;++j){
                    tmp.a[i+j-1]+=a[i]*nt.a[j];
                    tmp.a[i+j]+=tmp.a[i+j-1]/B;
                    tmp.a[i+j-1]%=B;
                }
            for(int i=1;i<=tmp.n;++i){
                tmp.a[i+1]+=tmp.a[i]/B;
                tmp.a[i]%=B;
            }
            tmp.work();
            return tmp;
        }
        inline huge_int operator / (const int &nt) const {
            huge_int tmp;
            tmp.clear();
            int x=0;
            tmp.n=n;
            for(int i=n;i>=1;--i){
                x=x*B+a[i];
                tmp.a[i]=x/nt;
                x%=nt;
            }
            tmp.work();
            return tmp;
        }
        inline huge_int operator += (const huge_int &nt) { return *this=*this+nt; }
        inline huge_int operator -= (const huge_int &nt) { return *this=*this-nt; }
        inline huge_int operator *= (const huge_int &nt) { return *this=*this*nt; }
        inline huge_int operator /= (const int      &nt) { return *this=*this/nt; }
    };
    inline huge_int gcd(huge_int a,huge_int b) {
        int na=0,nb=0;
        while(!(a.a[1]&1)) na++,a/=2;
        while(!(b.a[1]&1)) nb++,b/=2;
        int x=min(na,nb);
        while(a!=b){
            if(a<b) swap(a,b);
            a=a-b;
            while(!(a.a[1]&1)) a/=2;
        }
        huge_int t;
        t=2;
        while(x--) a*=t;
        return a;
    }
}
using namespace Huge_int;
using namespace std;
huge_int a,b;
signed main(){
    if(fopen("T1.in","r")){
        freopen("T1.in","r",stdin);
        freopen("T1.out","w",stdout);
    }
    a.rd();b.rd();
    gcd(a,b).wrt();
    return 0;
}

转载于:https://www.cnblogs.com/JCNL666/p/10645329.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值