题目来源:https://codeforces.com/contest/1988
写在前面
这是我们暑训的第一场cf比赛,因为隔了好几个星期没有认真刷题,这次的比赛打的依托······,签到题的A题都卡了我好久(一开始思路对的,被我自己驳回了好几次·····)
A-Split the Multiset
思路
签到题,每次都将n分为k-1个1,这样我们只需要考虑n-k+1的次数,循环到n小于等于k时结束,最后在答案多加上1次操作即可
编程
void solve(){
int n,k;
cin >> n >> k;
int sum=0;
if(n==1){
cout << 0 << endl;
return ;
}
if(n<=k){
cout << 1 << endl;
return ;
}
while(n>k){
sum++;
n=n-k+1;
}
cout << sum+1 << endl;
return ;
}
B-Make Majority
思路
首先我们的目标是尽可能让1多,0少,由于1的数目不可增加,所以我们就考虑减少0的个数,将连在一起的0全部变为1个0,比较1和0的个数即可
编程
void solve(){
int n;cin >> n;
string s;cin >> s;
int a=0,b=0;
int f=0;
for(int i=0;i<s.size();++i){
if(s[i]=='0'){
if(f==0) f=1;//标记连在一起的0
}
else{
b++;
if(f){
a++;
f=0;
}
}
}
if(f) a++;
if(a>=b){
cout << "no" << endl;
}
else cout << "yes" << endl;
return ;
}
C-Increasing Sequence with Fixed OR
思路
数列中最大的数为n,因此我们考虑反向构造,根据ai+1构造ai
为了保证数列递增,在二进制下从高位到低位一定是ai+1为1,ai为0,这样我们所能构造出的数列实际上就是n在二进制下1的个数(最后还要加上n本身)
记n在高位下二进制为2k0,2k1 ·····(k0>k1>·····),显然构造为
n
−
2
k
0
,
n
−
2
k
1
,
⋅
⋅
⋅
⋅
⋅
⋅
,
n
n-2^{k0},n-2^{k1},······,n
n−2k0,n−2k1,⋅⋅⋅⋅⋅⋅,n
例如:n=23(二进制下为10111)
它的序列为 23 23-20(22) 23-21(21) 23-22(19) 23-24(7)
最后颠倒一下序列即可
编程
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define fi first
#define se second
#define PII pair<int,int>
#define lowbit(x) ((x)&(-x))
using namespace std;
const int N=1e6+5;
void solve(){
int n;cin >> n;
vector<int> ans;
ans.push_back(n);
int k=n;
while(k){
int a=lowbit(k);
k-=a;
if(n-a) ans.push_back(n-a);//构造
}
reverse(ans.begin(),ans.end());
cout << ans.size() << endl;
for(auto i : ans){
cout << i << " ";
}
cout << endl;
return ;
}