[构造] UNR #1 Jakarta Skyscrapers

 

Jakarta Skyscrapers


被绍一的神犇们教导了
可以发现c肯定是Gcd的倍数
那么可以先用倍增模拟取模算出gcd
然后用gcd倍增出c
考试时没特判c>a && c>b 爆炸 20分

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> abcd;

abcd Stack[100005];
set<ll> Set;
int pnt;

inline void doit(ll a,ll b){
	if (Set.find(a-b)!=Set.end()) return;
	Stack[++pnt]=abcd(a,b);
	Set.insert(a-b);
}

inline void Calc(ll a,ll b){
	ll tmp=b;
	while (tmp*2<=(a/b)*b)
	{
		doit(a,tmp);
		doit(a-tmp,tmp);
		doit(a,a-tmp-tmp);
		tmp<<=1;
	}
	ll k=a/b; ll t2=a;
	for (int p=0;(1LL<<p)<=k;p++)
		if (k>>p&1)
		{
			doit(t2,(1LL<<p)*b);
			t2-=(1LL<<p)*b;
		}
}

ll a,b,c,d,g;

void Gcd(ll a,ll b){
	if (a%b==0) { g=b; return; }
	Calc(a,b);
	Gcd(b,a-(a/b)*b);
}

int main()
{
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	scanf("%lld%lld%lld",&a,&b,&c);
	if (a<b) swap(a,b); 
	if (c==a || c==b) return printf("0\n"),0;
	if (c>a) return printf("-1\n"),0;
	Gcd(a,b);
	if (c%g!=0) return printf("-1\n"),0;
	d=c/g;
	ll tmp=g;
	while (tmp*2<=c)
	{
		doit(a,tmp);
		doit(a-tmp,tmp);
		doit(a,a-tmp-tmp);
		tmp<<=1;
	}
	ll t2=a;
	for (int p=0;(1LL<<p)<=d;p++)
		if (d>>p&1)
		{
			doit(t2,(1LL<<p)*g);
			t2-=(1LL<<p)*g;
		}
	doit(a,t2);
	if (pnt>400) return printf("-1\n"),0;
	printf("%d\n",pnt);
	for (int i=1;i<=pnt;i++)
		printf("%lld %lld\n",Stack[i].first,Stack[i].second);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值