错题题目
1.优秀的拆分
2.小苹果
3.分糖果
优秀的拆分
样例:
我们先来看一下样例是怎么玩的
先说 6 是不是一个优秀的拆分,他可以分为 2 的 2 次幂,和 2 的 1 次幂,所以它是一个优秀的拆分,输出 2 ^ 2 也就是4 , 和 2 ^ 1 也就是2。但是这里有一个坑 2 ^ 0算不算优秀的拆分,注意审题呀,他说的是 2 的正整数次幂,所以2^ 0不算优秀的拆分
那我们来看一下这个题的思路:
既然知道了2 ^ 0不算优秀的拆分,那首先奇数是不是一定不算优秀的拆分。我们可以先判断是不是奇数,如果是直接输出-1,否则就把首位去掉,将n转换成二进制,如果在二进制的某一位上为1,则将对应的2的i次方存进数组中 ,为了从大到小输出,是不是要翻转一下数组(直接逆序输出也行),再输出。
标程:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
if(n % 2 == 1) return cout<<-1, 0;
n /= 2;
vector<int> ans;
//将n转换成二进制,如果在二进制的某一位上为1,则将对应的2的i次方存进数组中
for(int i = 2; n; i *= 2){
if(n % 2 == 1) ans.push_back(i);
n /= 2;
}
//反转数组,达到逆序输出的效果
reverse(ans.begin(), ans.end());
for(int a : ans) cout<<a<<' ';
return 0;
}
小苹果
这个题目类似于约瑟夫问题,只不过约瑟夫是个环。
样例:
小苞的桌上一共放了 8 个苹果。
小苞第一天拿走了编号为 1、4、7 的苹果。
小苞第二天拿走了编号为 2、6 的苹果。
小苞第三天拿走了编号为 3 的苹果。
小苞第四天拿走了编号为 5 的苹果。
小苞第五天拿走了编号为 8 的苹果。
思路:
每天拿走一个,每次间隔2个,也就是+3,到底了就回来,从头拿,数量不足就一个个拿。
标程:
#include <bits/stdc++.h>
using namespace std;
int take(int n) { // n个数字,每次拿走几个?
return n / 3 + (n % 3 > 0); // 拿走3的倍数+1
}
int f1(int n) { // n个数字,总共能拿几次呢?
if (n == 1) return 1;
return 1 + f1(n - take(n));
}
// n个数字,最后一个数字第几次拿走
int f2(int n) {
if (n % 3 == 1) return 1; // 最后一个数字是3的余数, 直接拿走
return 1 + f2(n - take(n)); // 可以再拿一次
}
int main() {
int n;
cin >> n;
printf("%d %d\n", f1(n), f2(n));
return 0;
}
分糖果
让我们来看一下题目中给的样例提示。
样例:
暴力代码90分:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
int ch, d, u, maxn=-1;
cin>>ch>>d>>u;
for(int i=d;i<=u;i++) maxn=max(maxn,i%ch);
return cout<<maxn,0;
}
最后一个u-d=1e9,就死了。
我们来看一下思路:
分析:为了使奖励尽可能多,理想情况就是使得分完之后的剩余糖果数是n-1,因此需要判断能否达到这个理想情况——当区间[L, R]能够完整覆盖一个长度为n的范围,说明一定存在一个数字k,使得k%n=n-1,因此只需要判断L/n是否与R/n一致;如果不能达到这个理想情况,则拿的越多越好,即答案为可以拿到的糖果上限R%n。
总体意思就是,如果在范围内,这个范围就是L~R,就拿最优解,就是n-1,否则就是R%n。
代码很简单:
#include<bits/stdc++.h>
using namespace std;
int main(){
int ch, d, u;
cin>>ch>>d>>u;
return cout<<(d / ch < u / ch ? ch-1 : u % ch),0;
}
谢谢。