zoukankan      html  css  js  c++  java
  • Codeforces Round #514 (Div. 2) C. Sequence Transformation(递归)

    C. Sequence Transformation

    题目链接:https://codeforces.com/contest/1059/problem/C

    题意:

    现在有1~n共n个数,然后执行下面操作:

    1.求出余下数的gcd,然后将gcd加入答案队列;

    2.从中任意删除一个数,如果余下数的个数大于0,回到步骤1。

    问答案队列字典序最大是什么。

    题解:

    这明明是递归在做极其方便,我偏偏用for循环来搞,加各种判断...

    首先对于1,2,3...n来说,我们每次删去一个数时,肯定首先删去的是奇数嘛,奇数有(n+1)/2个,也就是前(n+1)/2都为1。

    现在考虑如果不选奇数位置,答案有没有可能更优。更优的话考虑我们留下3,6,9....这样的(之前相当于我们留下2,4,6...这样的),即3的倍数。

    前n个有n/3个3的倍数,有n/2个2的倍数,容易验证当n>3时,2的倍数的个数是大于3的倍数的个数的。同理,可以验证留下4,5的倍数...

    会发现,当n>3时,2的倍数的个数是最多的,也就是我们删去的数个数是最少的,要求字典序最大,我们就留2的倍数就行了。对于n<=3,答案显而易见。

    之后的式子就是2,4,.....2*k,全为2的倍数,这个时候提取2出来,就变为2*(1+2+...+k),又回到刚才那个问题了。所以直接递归求解就是了。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n;
    vector <int> ans;
    void solve(int x,int y){
        if(x==1){
            ans.push_back(y);return ;
        }
        if(x==2){
            ans.push_back(y);ans.push_back(2*y);return ;
        }
        if(x==3){
            ans.push_back(y);ans.push_back(y);ans.push_back(3*y);return ;
        }
        int tmp=x;
        for(int i=1;i<=x;i+=2) ans.push_back(y),tmp--;
        solve(tmp,2*y);
    }
    int main(){
        cin>>n;
        solve(n,1);
        for(auto v:ans) cout<< v<<" ";
        return 0;
    }
  • 相关阅读:
    poj 1088 滑雪
    位运算与bitset
    hdu 4607 Park Visit
    树的直径
    codeforces 495D Sonya and Matrix
    German Collegiate Programming Contest 2015(第三场)
    BAPC 2014 Preliminary(第一场)
    Benelux Algorithm Programming Contest 2014 Final(第二场)
    E. Reachability from the Capital(tarjan+dfs)
    poj2104 K-th Number(划分树)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10398373.html
Copyright © 2011-2022 走看看