uoj#216. 【UNR #1】Jakarta Skyscrapers

题目描述


\(a,b,c \leq 10^{18}\)

题解

先除gcd

假设给出a和b,构出b,2b,4b,8b...2^kb(2^kb<a),那么显然是(a,b),(a-b,b),(a,a-2b)来使b*2

可以尝试每次乘4,发现结果是一样的

辗转相除求出gcd之后即可构出1,2,4,8...,之后减一下即可

用map去重,否则过不了

时间看似是log^2的,但是感受一下发现b每*2模完之后就可以少一次,因此应该是log*常数级别的

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

ll ans[401][2],A,B,C,s,Ans,t;
map<ll,bool> hs;
int i,j,k,l;

ll gcd(ll x,ll y) {ll r=x%y; while (r) x=y,y=r,r=x%y; return y;}
void add(ll x,ll y) {if (!hs[x-y]) ++Ans,ans[Ans][0]=x,ans[Ans][1]=y,hs[x-y]=1;}
void swap(ll &x,ll &y) {ll z=x;x=y;y=z;}

void work(ll x,ll y,bool bz)
{
	ll Y=y;
	while (Y*2<x)
	add(x,Y),add(x-Y,Y),add(x,x-2*Y),Y*=2;
	if (bz)
	{
		while (Y>=y)
		{
			if (x>Y) add(x,Y),x-=Y;
			Y/=2;
		}
	}
}
void Work()
{
	ll a=A,b=gcd(A,B),r=A%B;
	while (r) work(A,B,1),A=B,B=r,r=A%B;
	work(a,b,0);
	while (b*2<a) b*=2;
	while (a!=C)
	{
		if (a-b>=C) add(a,b),a-=b;
		b/=2;
	}
}

int main()
{
	#ifdef file
	freopen("uoj216.in","r",stdin);
	#endif
	
	scanf("%lld%lld%lld",&A,&B,&C);s=gcd(A,B);
	if (C%s || max(A,B)<C) {printf("-1\n");return 0;}
	A/=s,B/=s,C/=s;
	if (A<B) swap(A,B);
	hs[A]=hs[B]=1;
	
	Work();
	
	printf("%lld\n",Ans);
	fo(i,1,Ans) printf("%lld %lld\n",ans[i][0]*s,ans[i][1]*s);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-07-29 22:48  gmh77  阅读(111)  评论(0编辑  收藏  举报