题目链接:https://codeforces.com/contest/1154
A:Restoring Three Numbers
B:Make Them Equal
C:Gourmet Cat
D:Walking Robot
E:Two Teams
F:Shovels Shop
G:Minimum Possible LCM
A:给定b-a、a+c、b+c、a+b+c的值 求abc的值 (排序,做差求一下)
B:给定一个数组,现在有一个操作:对于数组的某个元素,你可以加或者减D(仅一次)。任务是将数组的所有值变成一样的。输出D的值,不存在输出-1。
放set里去重一下,是>3就-1,== 1 就是 0 , == 2,就是平均数做差,== 3,头尾搞一下就可以了,还要特判一下不相等,代码不放了。。。
C 你有只猫,周一、四、日吃鱼,周二、六吃兔肉。其余时间吃鸡肉。现在你要去旅行,且你准备了a份鱼、b份兔肉、c份鸡肉。求你在某天出门后这只猫能吃的的最大天数。(这个天数跟你周几出门有关
23333,这个题本来想抢一血的,结果我枚举的,忘了初始化,debug半天,wa4,改了就A了,就是取个Min,然后瞎判断一下,代码写的比较丑,就不放了。
D 有个机器人在0位置处,现在要走到位置n。机器人现在有一个电池容量为a,还有一个蓄电池容量为b(一开始都是满的)。数组的值代表此处有没有光照。走一格耗1电量,如果机器人使用电池行走并在太阳下时,蓄电池电量+1.(不能超过容量),求最远的行走距离 (我半天a和b搞反了,以至于自己花了40分钟才过这个傻逼题),当是1的时候,我们优先花可以不充电的电池,让可以充电的电池尽量充电,充满了就花不可以充电的(还要处理一下电池满的情况),是0的话就优先花可以充电的,
代码:(写的丑,勿喷。。。)
for(int i = 1; i <= n; i++) {
if(c[i]) {
if(b) {
if(a == x) a--;
else {
b--;
if(a < x)
a++;
}
} else {
if(a) a--;
else {
ans = i - 1;
break;
}
}
} else {
if(a) {
a--;
} else {
if(b) {
b--;
} else {
ans = i - 1;
break;
}
}
}
if(a == 0 && b == 0) {
ans = i;
break;
}
// cout << a << " " << b << endl;
}
cout << ans << endl;
E 有两个教练来选人,第一个先选。两个人选的策略是:找到还没被选的最大的一个。然后在选择它左边k个和右边k个。他们轮流选直到全部选完。输出他们都被谁选了
呃呃,直接链表模拟,赛后才过,一年没写数组模拟链表,debug了一个小时。。。菜的一匹,,,(注意最大值记录一下排名,不然会T)
ll n,k;
int a[maxn],l[maxn],r[maxn],ans[maxn],vis[maxn];
int main() {
ios::sync_with_stdio(false);
while(cin >> n >> k) {
sets;
for(int i = 1; i <= n; i++){
cin >> a[i],l[i] = i - 1,r[i] = i + 1;
vis[a[i]] = i;
s.insert(a[i]);
}
MS1(ans);
int id = 0, op = 1,num = 0;
while(1){
int Max = 0;
int id = vis[*s.rbegin()];
int ll = l[id],rr = r[id];
for(int i = r[id],cnt = 1;i <= n && cnt <= k;cnt++,i = r[i],rr = i){
ans[i] = op;
num++;s.erase(a[i]);
}
for(int i = l[id],cnt = 1;i >= 1 && cnt <= k ;cnt++,i = l[i],ll = i){
ans[i] = op;
num++;s.erase(a[i]);
}
ans[id] = op;
for(int i = r[id],cnt = 1;i <= n && cnt <= k;cnt++){
int x = r[i];
r[i] = rr;l[i] = ll;
i = x;
}
for(int i = l[id],cnt = 1;i >= 1 && cnt <= k ;cnt++){
int x = l[i];
r[i] = rr,l[i] = ll;
i = x;
}
l[id] = ll,r[id] = rr;
r[ll] = rr,l[rr] = ll;s.erase(a[id]);
num++;
if(num == n) break;
op ^= 1;
}
for(int i = 1;i <= n;i++) if(ans[i])cout << ans[i]; else cout << 2;
cout << endl;
}
cerr << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
F 你现在要买k把铲子,商店有n把铲子,价格数组给出。现在有m个优惠:如果一次买了x_i个铲子,那么其中前y_i个最便宜的铲子免费。一次只能使用一个优惠或者不使用。求最少花费。
首先我们可以排序,做个前缀和,可以跑个背包,f_i代表前i个铲子所需要的最少花费。
然后再枚举每个优惠使用情况
转移可以有f[i] = min(f[i - p[i].fi] + s[i] - s[i - p[i].fi + p[i].se],f[i]) 前面的部分很容易理解,背包的模型,后面
首先f[i - p[i].fi] 就是 3 部分 ,我们知道如果买fi个,前se可以免费,而我们要加的是1部分,那怎么求呢
就是s[i] - s[i - p[i].fi + p[i].se],可以求到,s[i - p[i].fi + p[i].se]就是 2 和 3部分的和
ll c,n,k,m;
P p[maxn];
ll a[maxn],f[maxn],s[maxn];///fi代表买i个铲子的最小花费。
int main() {
ios::sync_with_stdio(false);
while(cin >> n >> m >> k){
for(int i = 1;i <= n;i++) cin >> a[i];
sort(a + 1,a + 1 + n);
for(int i = 1;i <= n;i++) s[i] = s[i - 1] +a[i];
// for(int i = 1;i <= n;i++) cout <> p[i].fi >> p[i].se;
}
for(int i = 1;i <= k;i++){
for(int j = 1;j <= m;j++){
if(i >= p[j].fi)
f[i] = min(f[i - p[j].fi] + s[i] - s[i - p[j].fi + p[j].se],f[i]);
}
}
cout <
G 给定数组,求其中lcm(a,b)的最小的a和b的位置。
呃呃,这个题可以参考以前做的 https://blog.csdn.net/qq_38185591/article/details/88293190,同样的方法,用筛法搞一下,cf确实能跑1e7的n*log的,而且开了4s,枚举gcd,然后倍数超过2了就直接更新一下,按题中要求找最小的。还要再处理一下重复的地方。
ll vis[maxn];
mapm;
int main() {
ios::sync_with_stdio(false);
while(cin >> n){
m.clear();
ll Max = 0;
ll anss = 1e18;
vectorans,ansss;
for(int i = 1;i <= n;i++){
ll x;
cin >> x;
if(vis[x]){
if(x < anss){
ansss.clear();
ansss.push_back(vis[x]);
ansss.push_back(i);
anss = x;
}
}
vis[x] = i;
}
for(ll i = 1;i <= 1e7;i++){
ans.clear();
for(ll j = i;j <= 1e7;j += i){
if(vis[j]) ans.push_back(j);
if(ans.size() >= 2) break;
}
if(ans.size() >= 2){
ll Max = ans[0] * ans[1] / i;
if(Max < anss){
anss = Max;
ansss.clear();
ansss.push_back(vis[ans[0]]);;
ansss.push_back(vis[ans[1]]);
}
}
}
sort(ansss.begin(),ansss.end());
for(auto d:ansss)
cout << d << " ";
}
cerr << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}