【题目链接】

题意

给你一个n,有1-n共n个数字,每次操作求一下剩余数字的最大公因数,再删去一个数字,执行n次操作。
令n次操作的最大公因数排成一个序列,求该序列字典序的最大值

Examples

input
3
output
1 1 3
input
2
output
1 2
input
1
output
1

Note

In the first sample the answer may be achieved this way:

Append GCD(1,2,3)=1(1,2,3)=1, remove 2.
Append GCD(1,3)=1(1,3)=1, remove 1.
Append GCD(3)=3(3)=3, remove 3.
We get the sequence [1,1,3] as the result.

思路

首先在纸上模拟前几项。
1.发现一定是先取走奇数
当n为奇数时,取走n/2+1个奇数(即输出n/2+1个1),当n为偶数时,取走n/2个奇数(即输出n/2个1)。

当n=16时

第一次后剩余元素 2 4 6 8 10 12 14 16
输出8个1

当前最大公因数为2

此时第九个元素为2,没有其他取法大于当前序列。

2.发现一定是抽空取

当n=16时

第一次后剩余元素 2 4 6 8 10 12 14 16
输出8个1

第二次后剩余元素 4 8 12 16
输出4个2

当前最大公因数为4

此时第13个元素是4,没有其他取法大于当前序列。

3.当n=3或者说当前剩了3个元素

例如 剩余元素 4 8 12
显然第一次取走4,第二次8,第三次12是最优选择。
而我们之前的结论顺序是4,12,8。

所以我们需要在n=3的时候加上特判,判断最后一个元素能否变大(赛时是这样想的,后来发现当n=3时一定是1:1:3的比例,所以这里也可以直接输出)。不过赛时我发现只会影响到最后一个输出,所以特判了最后一个能否倍增来解决。

AC代码

#include <iostream>
using namespace std;
int main()
{
	int n, nn;
	scanf("%d", &n);
	nn = n;
	for (int i = 0; n != 0; i++)
	{
		int a = n / 2;
		int b = n - a;
		for (int j = 0; j < b; j++)
			printf("%d ", 1 << i);
		n = a;
		if (n == 1)
		{
			int t = 1 << i;
			int tt = t;
			while (tt + t <= nn)
				tt += t;
			printf("%d", tt);
			return 0;
		}
	}
}