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; }