• ARC122C-Calculator【乱搞,构造】


    正题

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


    题目大意

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

    (1leq nleq 10^{18})


    解题思路

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

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

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

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

    所以我们让(k=n imes 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
    ",z.size());
    		for(ll i=0;i<z.size();i++)
    			printf("%lld
    ",z[i]);
    		break;
    	}
    	return 0;
    }
    
  • 相关阅读:
    最火的.NET开源项目[转]
    ExtJs4.1目录结构介绍和使用说明[转]
    mvc4 Forms验证存储 两种登录代码
    微服务 第九章 springboot 使用NoSql数据库:redis
    【数据挖掘】关联分析之Apriori(转载)
    C语言面试
    10.15习题2
    java 执行linux命令
    servlet tomcat eclipse
    002_监测ssl证书过期时间
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14879560.html
Copyright © 2020-2023  润新知