A. Split the Multiset
题意:给定一个数,可以进行若干次操作,每次可以将它拆分成不超过k个数,问最少多少次操作可以将该数全部拆为1。
思路:找规律,可以发现每次将最大的数S拆为k-1个1和1个S-(k-1)直到最大的数S为1即可,代码如下:
void solve(){
int n,k;
cin >> n >> k;
int ans = 0;
while(n > 1){
n -= (k-1);
ans+=1;
}
cout << ans << endl;
}
B. Make Majority
题意:给定一个01序列,进行若干次操作,每次操作可以指定任意一个区间的数变为该区间内出现最多的数,问最终能否将该序列变为只包含一个1。
思路:先把所有连续的0合并为一个0,最后判断0和1的数量即可。代码如下:
void solve(){
int zero = 0,one = 0;
int n;
cin >> n;
bool last = false;
for(int i = 1;i<=n;i++){
char c;
cin >> c;
int num;
num = c - '0';
if(num == 0){
last = true;
}if(num != 0 and last){
last = false;
zero++;
one++;
}else if(num != 0){
one++;
}
}
if(last)
zero++;
if(zero >= one)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
C. Increasing Sequence with Fixed OR
题意:给定一个正整数n,求一个序列a,a中元素满足a[i] | a[i-1] = n , 并且a序列递增,求该序列最大长度并输出。
思路:找规律,要使得两两或运算结果都为n,并且递增,我们可以将n转为二进制,该二进制包含多少个1的数量+1即为该序列最大长度,然后从该二进制最高位开始,往前忽略一个二进制位的1输出它的值即可,代码如下:
void solve(){
int n;
int a[70];
bool vis[70];
cin >> n;
int k = 0;
int maxN;
for(int i = 0;i<=63;i++){
if(n >> i & 1){
a[i] = 1;
k++;
maxN = i;
vis[i] = true;
}else{
a[i] = false;
vis[i] = false;
}
}
if(k == 1){
cout << 1 << endl << n << endl;
return;
}
cout << k+1 << endl;
for(int i = 1;i<=k+1;i++){
bool ok = true;
int num = 0;
for(int j = maxN;j>=0;j--){
if(vis[j] and ok and i != k+1){
vis[j] = false;
ok = false;
continue;
}
if(a[j] == 1){
num += fastPower(2,j);
}
}
cout << num << " ";
}
cout << endl;
}
优化:快速幂,代码如下:
int fastPower(int num, int power) {
int result = 1;
while (power > 0) {
if (power & 1) { //if(power%2==1)
result = result * num;//result = result * num%mod
}
power >>= 1; //power=power/2
num = (num * num);//num = (num * num)%mod
}
return result;
}