1. 程式人生 > >codeforces round 514div2C Sequence Transformation(思維+找規律)

codeforces round 514div2C Sequence Transformation(思維+找規律)

題意

給出一個長度為 n n 的序列,初始序列為 1 , 2 , 3 ,

, n 1,2,3,\dots,n ,每次計算出當前序列的 G C D GCD
並輸出,然後可以任意刪除序列中的一個數,重複前面操作,直到整個序列為空。要求輸出的 G C D GCD 序列字典序最大。

亂搞題解

很明顯最後的GCD序列長度是 n

n ,通過手算幾個樣例我發現了當 n > 3 n > 3 時一個規律,輸出的GCD都是 2 i 2^i ,每4個 2 i 2^i 出現的次數是 c n t = n 2 i 2 i + 1 + 1 cnt = \frac{n-2^i}{2^{i+1}}+1 ,當 i = = 0 i == 0 n n 為奇數時, c n t + 1 cnt+1 其餘的時候可以當做 n 1 n-1 處理 。但這個需要特殊處理一下最後一次的GCD,最後的數字是 n / l a s t ( 2 i ) l a s t ( 2 i ) n/last(2^i)*last(2^i) l a s t ( 2 i ) last(2^i) 代表的是在 n 1 n-1 處出現的 2 i 2^i

正規題解

可以發現一開始需要刪除掉全是奇數的數字 c n t cnt 個,輸出 c n t cnt 個1,之後剩下的都是 2 , 4 , 6 , 8 , 2,4,6,8,\dots 的序列,這相當於 1 , 2 , 3 , 4 , 1,2,3,4,\dots 乘一個2,所以問題還是和前面一樣,刪除下標為奇數的數字 c n t cnt 個,然後輸出最前面的那個數字 c n t cnt 個。
然後不斷將問題縮小,當 n 3 n \leq 3 時要特殊處理一下。

亂搞程式碼

#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b) {
	return b == 0 ? a: gcd(b,a%b);
}
int main() {
	int n;
	scanf("%d", &n);
	int cnt = 0;
	if(n <= 3) {
		if(n == 3)
			cout <<"1 1 3" << endl;
		if(n == 2)
			cout << "1 2" << endl;
		if(n == 1)
			cout << 1 << endl;
		return 0;
	}
	int last;
	int sum = 0;
	int p = 1;
	sum++;
	cout << p << " ";
	last = p;
	int f = 2;
	int t = n;
	while((n-p)/f > 0) {
		int cnt = (n-p)/f;
		if(n&1) n--;
		for(int i = 0; i < cnt; ++i)
			cout << p <<" ";
		sum += cnt;
		last = p;
		p *= 2; f *= 2;
		if(sum < t-1) {
			sum++;
			cout << p <<" ";
			last = p;
		}
	}
	cout << n/last*last << 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;
}