2020.12.27 ICPC 济南站 回顾
开始直接冲A题,翻译完一波,然后看看其他题目的情况,发现两道签到题,M题和G题,马上转战M题,hx直接得出结论,提交一波,WA,共同讨论一下马上发现问题所在,AC
A题
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
if(k >= n) cout << 2 << endl;
else {
int ans = n * 2 / k;
if((n * 2) % k != 0) ans++;
cout << ans << endl;
}
return 0;
}
然后接着去写G题,hx琢磨一会儿得出了恒定一种方法的结论:x ^ (x ^ y) ,令z = x ^ y, 这样只需要一次 x ^ y即可得到 y ,提交一次WA,返回仔细检查发现 z 是有可能大于等于 x 的,所以需要分情况,大于 x 的情况怎么处理呢,hx继续琢磨,得出恒定两种方法的结论 首先 x ^ [x]反 得到 x = 全1,然后再 x ^ [y]反 得到 y,所以结果是 两次操作, 第一次操作的 A = (同x二进制位数的全1 异或 x),第二次操作的 A = (同x二进制位数的全1 异或 y),想法已经出来,马上码代码,结果WA,后面陆陆续续提交了3,4次,于是 zyj 立马转战C、D题,hx 和 我 继续磕G题,在计算全1和反码上 xqm 使用了字符串写法,结果还是错误,然后陆续提交了3次,最终发现 hx 修改了一个强制转换的位置,AC,赛后我仔细分析,发现我们原先计算全1的代码:ll ans = (ll)(pow(2, cnt) - 1); cnt是 x 的二进制位数,发现当pow计算的最多可达10^18,pow返回double值,由于double精度有限,10进制有效位大概在15~16位,所以在计算过程中可能会出现精度损失,导致结果出错。AC时的代码:ll ans = ((ll)pow(2, cnt) - 1); 仔细反思了一下,这个代码其实也是可能出错的,可能刚好测试点通过pow时是没有出现精度损失的,下面放出赛后修改后的代码
G题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
ll x, y;
cin >> x >> y;
ll ans = 1;
while(ans <= x) {
ans <<= 1;
}
ans--;
cout << 2 << endl;
cout << (ans ^ x) << " " << (ans ^ y) << endl;
return 0;
}
C题是在G题前面被 zyj 一次AC的,真好,大致思路是石头数量为3的石堆是不用管,不需要花钱,然后石头数量为1的堆和石头数量为2的堆互相结合,花的钱为堆数较少者的堆数*2,然后有剩余的堆再单独分情况,目前我思路还不清除,等我理清楚了再补。
C题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
ll a, b, c;
cin >> a >> b >> c;
ll ans = 0;
if (a > b) {
ans = b * 2;
int tmp = a - b;
int xx = (tmp - 1) / 3, yy = (tmp - 1) % 3;
if(yy == 0) ans += xx * 3;
else if (yy == 1) ans += xx * 3 + 1;
else if(yy == 2) ans += xx * 3 + 3;
}
else if (a == b) ans = b * 2;
else {
ans = a * 2;
int tmp = b - a;
int xx = (tmp - 1) / 3, yy = (tmp - 1) % 3;
if(yy == 0) ans += xx * 6;
else if (yy == 1) ans += xx * 6 + 4;
else if (yy == 2) ans += xx * 6 + 6;
}
cout << ans << endl;
}
C题G题过了后转战D题,开始的时候是在纠结原计划是啥,zyj 肯定原计划是所有人都选择最大值Ri,后面仔细琢磨题意,确实是这样,没有疑问后我直接开做,大致思路是先按照R值升序排序,然后如果相同R值的点取它们中最大L值,且保证
这个值不能小于等于左边不是相同R值的点,这样能保证现在每个人的分数不会小于原先的分数,因为我将分数保证了和之前是一样的,而且能得到最小sum,结果一交,WA,后面 hx 也撸了个代码,结果也WA了,后面琢磨了半天,WA了好几次,然后读了好几次题目,发现其他每个人的分数其实是可以提高的,只要不小于即可,好了修改了一个小细节后,AC,还是得吸取教训,多读题。
D题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
struct node {
int L, R, s;
} st[maxn];
bool cmp(node a, node b) {
if(a.R != b.R) return a.R < b.R;
return a.L > b.L;
}
int main() {
int n; cin >> n;
for(int i = 1; i <= n; i++) cin >> st[i].L >> st[i].R;
sort(st+1, st+n+1, cmp);
st[0].L = st[0].R = st[0].s = -1;
for(int i = 1; i <= n; i++) {
if(st[i].R != st[i-1].R) {
if(st[i].L > st[i-1].s) st[i].s = st[i].L;
else st[i].s = st[i-1].s;
}
else st[i].s = st[i-1].s;
}
ll sum = 0;
for(int i = 1; i <= n; i++) sum += st[i].s;
cout << sum << endl;
}
写完D题,发现已经排到了400多,气人,人均4题,按照我们队伍的目前这个情况,只有再做一题才有可能拿奖,哎,继续冲A题,这个点时间已经不多,磨了半天,发现没啥思路,只能发现结果大概是2的多少次方,然后我们就根据测试样例开始盲猜,特判,哎,没办法,是真滴cai。
其他题目这几天补一补,看能不能再做出几个。
第一次ICPC分站赛到此结束,打铁了还是挺可惜的,不过潜力还是蛮大的,差不多是第一次正式接触ICPC分站赛,大概训练了不到一个月吧,之前没怎么打过这种思维题目,不太习惯,发现前面几道题基本上都不涉及什么算法,纯思维,想到了就出来了,以后还是得多做这种题目吧,冲,明年ICPC见,希望明年能拿个铜,哎