UNR 1 DAY 2 T1 Jakarta Skyscrapers

不妨设a>b。

当c>a || gcd(a,b)!=gcd(a,b,c) 时无解。

我们考虑倍增法。

a%b 这一操作可以从此转移而来:

 a       b

 a-b     b

 a        a-2b

 a        2b

 a-2b    2b

 a-2b    2b

   ……

我们先求出gcd(a,b)(倍增法取代%)

 然后再对a减去(a-c) (同样用倍增法)

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL t[407],p[407],a,b,c,siz,o,T,oo;
void gcd(LL a,LL b){
    if (a<b) swap(a,b);
    if (b==T) return;
//     printf("%d %d\n",a,b);
//    t[++o]=a; p[o]=b;
    LL j=a/b; 
    if (j<5) {
     t[++o]=a; p[o]=b;
     gcd(a-b,b);
     return; }
    t[++o]=a; p[o]=b; 
     siz=b;
    while (siz<a) {
        t[++o]=a-siz; p[o]=siz;
        if (siz*2<a) t[++o]=a,p[o]=a-siz*2;
        siz<<=1;
    }
    while (j) {
        LL L=j&(-j);
        t[++o]=a; p[o]=L*b;
        a-=p[o]; j-=L;
    }
    gcd(b,a%b);
} 
//LL a,b,c,t,x,y;
signed main () {
//    freopen("u1.in","r",stdin);
    scanf("%lld%lld%lld",&a,&b,&c);
    if (a<b) swap(a,b);
    if ((T=__gcd(a,b))!=__gcd(a,__gcd(b,c))
    ||c>a) return puts("-1"),0;
    gcd(a,b);
    siz=T;
    t[++o]=a; p[o]=siz;
    while (siz<a) {
        t[++o]=a-siz; p[o]=siz;
        if (2*siz<a) 
         t[++o]=a,p[o]=a-2*siz;
        siz<<=1;
    }  
//    cerr<<T<<endl;
    LL g=(a-c)/T;
    while (g) {
        LL L=g&(-g);
        t[++o]=a; p[o]=L*T;
        a-=p[o]; g-=L;
    }    
    for (int i=1;i<=o;i++)
     if (t[i]<=p[i]) oo--;
    oo+=o;
    printf("%lld\n",oo);
    for (int i=1;i<=o;i++) {
      if (t[i]>p[i]) printf("%lld %lld\n",t[i],p[i]);
    } return 0;
}

 

posted @ 2018-07-16 16:17  泪寒之雪  阅读(186)  评论(0编辑  收藏  举报