[ CodeForces 1059 C ] Sequence Transformation
\(\\\)
\(Description\)
你现在有大小为\(N\)的一个数集,数字分别为 \(1,2,3,...N\) ,进行\(N\)轮一下操作:
- 输出当前数集内所有数的\(GCD\)
- 从数集中去掉一个数
现在有你确定操作序列,使得输出序列的字典序最大,只需要输出按照你的操作顺序下的输出序列即可。
- \(N\in [1,10^6]\)
\(\\\)
\(Solution\)
考虑最优答案,一定有相当一段长度为\(1\),然后出现了第一个不为 \(1\)的答案。
这个答案一定是 \(2\) 。考虑如果想让答案第一个非\(1\)的是\(3\),就必须去掉所有模三剩余系下不为 \(0\) 的数,显然这个需要去掉的数所构成的数集是远大于由模二剩余系所确定的数集的。
然后考虑将所有奇数去掉以后局面就会变成一个所有的偶数集,显然此时让集合内所有数都除以二有转化为了前一个问题,同样的方法。
具体实现每次只需要输出当前待删除的数字个数个答案,再将答案乘以二,集合大小除以二即可。
特殊的,对于当前只剩下三个数字的情况,序列 \(1,1,3\) 是要比 \(1,1,2\) 要优秀的,注意特判边界。
\(\\\)
\(Code\)
#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define R register
#define gc getchar
using namespace std;
int n,ans=1,tmp;
int main(){
scanf("%d",&n);
while(n){
if(n==3){printf("%d %d %d",ans,ans,ans*3);return 0;}
if(n==2){printf("%d %d",ans,ans*2);return 0;}
if(n==1){printf("%d",ans);return 0;}
tmp=(n+1)/2;
for(R int i=1;i<=tmp;++i) printf("%d ",ans);
n=n/2; ans<<=1;
}
return 0;
}