1. 程式人生 > >CF C. Sequence Transformation【規律】

CF C. Sequence Transformation【規律】

題意:給你一個n  然後代表1到n的一個序列

然後說每次進行一種操作  序列當前所有數的gcd   然後把gcd結果加入一個答案陣列   然後此時可以刪除序列中的一個數

重複這種操作 直至序列沒有數  同時保證答案序列是字典序最大  前面的數越大越好

收穫:樣例一般都會 給出具有代表性   而且比較特殊的  我們應該善於發現

首先1 2 3 4 5 6 7 8 。。。n

很明顯 這些數的gcd就是1

怎麼刪除數:可以發現這n個數中  1的倍數個數  >2的倍數個數 >3的倍數個數>4的倍數個數 

所以想到了 把2的倍數保留下來 其餘的刪走   就是有刪走個數  個1

同理  再把4的倍數保留下來  其餘的刪走   就是有刪走個數  個2

同理  再把8的倍數保留下來  其餘的刪走   就是有刪走個數 個4

同理  再把16的倍數保留下來  其餘的刪走   就是有刪走個數 個8

同理  再把32的倍數保留下來  其餘的刪走   就是有刪走個數 個16

。。。。直到沒數

畫了一下可以發現  每次刪除的個數就是  即n  -  n/2  向下取整   

刪完每次剩餘的是   沒刪除之前的n    除以  2    個

1 2 3 4 5    5個

2 4             2個

4                1個

1 2 3 4 5 6 7 8 9 10  11  12 13 14 15 16              16個

2 4 6 8 10 12 14 16                                               8個

4 8 12 16                                                               4個

8 16                                                                        2個

16                                                                            1個

現在知道了 答案陣列 加入的數(1  2  4  8  16。。。。)

又知道了每次刪除應該 加多少個上面的數   n  -  n/2個

#include<iostream>

using namespace std;

const int maxn = 1e6 + 100;
int ans[maxn];
int lc;
int main(){
	
	int n;
	while (cin >> n){
//		if (n == 3){
//			cout << "1 1 3" << endl;
//			continue;
//		}
		lc = 0;
		//要加的數 
		for (int add = 1;n;add*=2){
			//看樣例 3   輸出 1 1 3 猜的  因為1 2 3 最優不是為了儲存2倍數 而刪除 1 和 3  而是刪除1 和 2  
			if (n == 3){
				ans[lc++] = add, ans[lc++] = add, ans[lc++] = add * 3;
				break;
			}
			int many = n - n/2;//刪除的個數   加上刪除個數 個 add 
			for (int j = 0; j < many; ++j){
				ans[lc++] = add;
			}
			n = n / 2;//更新序列 
		}
		for (int i = 0; i < lc;++i){
			cout << ans[i] << " ";
		}
		cout << endl;
		
	}
	return 0;
}

官方題解是利用    每次刪除都是  奇數位 

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e6 + 6;

int seq[maxn];
int ans[maxn];
int ptr = 0;

void solve(int n, int mul){
	if(n == 1){ans[ptr++] = mul; return;}
	if(n == 2){ans[ptr++] = mul; ans[ptr++] = mul * 2; return;}
	if(n == 3){ans[ptr++] = mul; ans[ptr++] = mul; ans[ptr++] = mul * 3; return;}
	for(int i = 0; i < n; i++)if(seq[i]&1)ans[ptr++] = mul;
	for(int i = 0; i < n/2; i++)seq[i] = seq[2*i + 1]/2;
	solve(n/2, mul * 2);
}

int main(){
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; i++)seq[i] = i + 1;
	solve(n, 1);
	for(int i = 0; i < n; i++)printf("%d ", ans[i]);
	return 0;
}