codeforces round 514div2C Sequence Transformation(思維+找規律)
阿新 • • 發佈:2018-11-01
題意
給出一個長度為 的序列,初始序列為 ,每次計算出當前序列的 並輸出,然後可以任意刪除序列中的一個數,重複前面操作,直到整個序列為空。要求輸出的 序列字典序最大。
亂搞題解
很明顯最後的GCD序列長度是 ,通過手算幾個樣例我發現了當 時一個規律,輸出的GCD都是 ,每4個 出現的次數是 ,當 且 為奇數時, 其餘的時候可以當做 處理 。但這個需要特殊處理一下最後一次的GCD,最後的數字是 , 代表的是在 處出現的 。
正規題解
可以發現一開始需要刪除掉全是奇數的數字
個,輸出
個1,之後剩下的都是
的序列,這相當於
乘一個2,所以問題還是和前面一樣,刪除下標為奇數的數字
個,然後輸出最前面的那個數字
個。
然後不斷將問題縮小,當
時要特殊處理一下。
亂搞程式碼
#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;
}