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;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/10398373.html

时间: 2024-08-30 14:47:09

Codeforces Round #514 (Div. 2) C. Sequence Transformation(递归)的相关文章

Codeforces Round #514 (Div. 2) C. Sequence Transformation 思维构造

题意 给出一个1-n的集合   gcd 集合里面的所有数  得到的 一个 数   然后自己选择删去一个数   要使得到的数 构成的数列 的字典序最大 思路: gcd所有数 那gcd得到的数肯定要小于数组中最小的数  所以 刚开始都是1   所以优先删去1  那就要使gcd所有数经可能快得到 2 如何快速到2 呢 那就是把奇数全部删掉  那剩下得数最小就为2 了  此时为 2 4 6 8 10....  此刻就从2开始删   当n==3时 有 x ,2x,3x  此时 只有 删 x 2 x   3

贪心+构造 Codeforces Round #277 (Div. 2) C. Palindrome Transformation

题目传送门 1 /* 2 贪心+构造:因为是对称的,可以全都左一半考虑,过程很简单,但是能想到就很难了 3 */ 4 /************************************************ 5 Author :Running_Time 6 Created Time :2015-8-3 9:14:02 7 File Name :B.cpp 8 *************************************************/ 9 10 #include

Codeforces Round #514 (Div. 2)

1059A - Cashier #include<cstdio> const int N=1e5+5; int l[N],t[N]; int main(){ int n,L,a,ans=0; scanf("%d%d%d",&n,&L,&a); for(int i=1;i<=n;++i) scanf("%d%d",&t[i],&l[i]); if(l[1]) ans+=t[1]/a; t[n+1]=L; for

Codeforces Round #514 (Div. 2) D. Nature Reserve

http://codeforces.com/contest/1059/problem/D 最大值: 最左下方和最右下方分别有一个点 r^2 - (r-1)^2 = (10^7)^2 maxr<0.5*10^14 Way1: 二分. difference: 如果使用 5*10^13 -> 10^-6,2^ 60~70区间,pow,sqrt运算,实测超时. 实际上是,使用. time of a case:-> Code: 1 #include <bits/stdc++.h> 2

Codeforces Round #153 (Div. 1) C Number Transformation bfs

//到达2 , 3 ... k的最小公倍数为lcm //当x到达lcm的倍数时,x只能减一 //又从a到b一定会过lcm的倍数 //我们将a,b以lcm分割 //那么完整的lcm段的最小数是相同的,所以我们只需要计算一个lcm段的最小值乘以完整lcm段的个数 //以及首尾的不全的lcm段的和即为答案 #include<cstdio> #include<cstring> #include<iostream> #include<queue> using name

CodeCraft-19 and Codeforces Round #537 (Div. 2) A - Superhero Transformation

题目描述 We all know that a superhero can transform to certain other superheroes. But not all Superheroes can transform to any other superhero. A superhero with name ss can transform to another superhero with name tt if ss can be made equal to tt by chan

Codeforces Round #529 (Div. 3) E. Almost Regular Bracket Sequence (思维)

Codeforces Round #529 (Div. 3) 题目传送门 题意: 给你由左右括号组成的字符串,问你有多少处括号翻转过来是合法的序列 思路: 这么考虑: 如果是左括号 1)整个序列左括号个数比右括号多 2 2)在这个位置之前,所有位置的前缀左括号个数都不少于前缀右括号个数 3)在这个位置和这个位置之后,在修改后所有位置的前缀左括号个数减去前缀右括号个数大于2 (这里这么想,把左变成右,左-1,右+1) 右括号也是这样 代码: #include<bits/stdc++.h> usi

【codeforces】Codeforces Round #277 (Div. 2) 解读

门户:Codeforces Round #277 (Div. 2) 486A. Calculating Function 裸公式= = #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; LL n ; int main () { while ( ~scanf ( "%I64d" , &n )

Codeforces Round #315 (Div. 1)

A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Rikhail Mubinchik believes that the current definition of prime numbers is obsolete as they are too complex and un