传送门:http://codeforces.com/contest/1059/problem/C
这个c题还挺有意思的,一开始实在是看不懂题,后来理解了,要字典序(误)最大,就必须越快增加整个数列的gcd越好。
注意到这个数列是有序而且从1到n,那么先假设n比较大,这个时候gcd是1,我们要删掉最少的数让gcd改变,最少删掉多少呢?
n范围内,是2这个数的倍数的数的个数,永远比是其他数的倍数的数的个数多,那么我们就要让这个gcd优先变成2,也就意味着我们要删掉所有的奇数,剩下的都是偶数,那么我们发现又要让gcd最快变化,我们就要让gcd变成4,就把所有不是4倍数的删去,然后是8,然后是16 。。。 类推。
那么删到最后,我们会发现,剩下的数字要么是3个,要么是两个,如果剩下两个数,我们假设当前gcd = a,那么我们剩下的两个数就是 a,2*a, 那么如果剩下三个数 那就是 a , 2a, 3a 我们发现对于两个的我们还是像上述的那样把不是gcd*2的倍数的数删掉,最后可以让gcd*2,但是对于剩下三个数的情况,我们如果还是这样删掉的话,2次删除过后,gcd增加到了2*gcd,但是我们如果把前两个数删掉的话,gcd增加到了3*gcd,那么这个情况的字典序肯定是比之前的那种要大,那么我们就对剩下3个数的时候特判即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int gcd(int a,int b){if (b == 0) return a; return gcd(b , a%b);}
int lcm(int a, int b){ return a/gcd(a,b)*b;}
inline int read(){
int f = 1, x = 0;char ch = getchar();
while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
int main(){
int n,cnt1,cnt2,now = 1,temp;
cin >> n; temp = n;
while(n > 0){
if (n == 3) {
printf("%d %d %d\n",now,now,now*3);
break;
}
if (n & 1) {cnt1 = n/2+1; cnt2 = n/2;}
else cnt1 = cnt2 = n/2;
while(cnt1 > 0) {printf("%d ",now);cnt1--;}
n = cnt2;
now <<= 1;
}
return 0;
}