ARC122C-Calculator乱搞,构造

Posted QuantAsk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARC122C-Calculator乱搞,构造相关的知识,希望对你有一定的参考价值。

正题

题目链接:https://atcoder.jp/contests/arc122/tasks/arc122_c


题目大意

一个数对开始是\\((0,0)\\),每次可以选择一个数加一或者让一个数加上另一个数,求使得第一个数变成\\(n\\)的方案。步数不超过\\(130\\)

\\(1\\leq n\\leq 10^{18}\\)


解题思路

官方是斐波那契,但是我考试的时候过法比较神奇。

看上去比较像更相减损,但是不知道第二个数是多少,感觉我们应该能找到一个数对\\((n,k)\\)使得它更相减损的步骤很少。

考虑的分散一点,设\\(n=xk+k\\)。那么我们相当于要找到一个\\(x\\)使得\\(\\frac{xk+k}{k}=\\frac{1}{x}\\)

然后解出来得到\\(x=\\frac{\\sqrt 5-1}{2}\\)(其实就是黄金分割率)。

所以我们让\\(k=n\\times \\frac{\\sqrt 5-1}{2}\\)然后更相减损下去,之后会发现有点误差,我们前后各枚举\\(10000\\)找到一个满足条件的就好了。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define ll long long
using namespace std;
ll n;vector<ll> z;
void print(ll x,ll y){
	if(!x){while(y&&z.size()<=130)y--,z.push_back(2);return;}
	if(!y){while(x&&z.size()<=130)x--,z.push_back(1);return;}
	if(x<y) print(x,y-x),z.push_back(4);
	else print(x-y,y),z.push_back(3);
}
signed main()
{
	scanf("%lld",&n);
	double M=(sqrt(5.0)-1.0)*(double)n/2.0;
	ll m=M;
	for(ll i=max(m-10000,0ll);i<=m+10000;i++){
		print(n,i);
		if(z.size()>130){z.clear();continue;}
		printf("%lld\\n",z.size());
		for(ll i=0;i<z.size();i++)
			printf("%lld\\n",z[i]);
		break;
	}
	return 0;
}

以上是关于ARC122C-Calculator乱搞,构造的主要内容,如果未能解决你的问题,请参考以下文章

atcoderAll Your Paths are Different Lengths[arc102D](乱搞)

ARC122CCalculator

ARC122A Many Formulae 题解

[ARC122E]Increasing LCMs

[ARC 122]

[ARC122C] Calculator