2021CCPC网络预选赛(第一场)赛后团队小结
比赛信息:
比赛名称: 2021中国大学生程序设计竞赛(CCPC)- 网络选拔赛
组织方:杭州电子大学 && CCPC组委会
比赛形式:线上
赛制:ACM / 团体
队伍信息:
队名:高等数学半价出售
队长:魏道(题目思路、测试集)
队员1:王晨杰(主码手)
队员2:黄文豪(副码手、读题)
比赛过程回顾:
第1题 | 第2题 | 第3题 | 第4题 | 第5题 | 第6题 | 第7题 | |
提交次数 | 3 | 0 | 0 | 0 | 0 | 1 | 0 |
首次提交时间 | 00:21:49 | 04:44:15 | |||||
首A时间 | 01:03:43 |
第8题 | 第9题 | 第10题 | 第11题 | 第12题 | 第13题 | |
提交次数 | 0 | 2 | 0 | 0 | 0 | 0 |
首次提交时间 | 02:08:58 | |||||
首A时间 | 02:54:24 |
A. Cut The Wire
tag:
⇔模拟、⇔简单数论(冰雹数)
题意:
对无限多个路灯进行编号,从 \(1\) 一直到 \(+\infty\) 。
这些路灯互相有电线相连,规则是:
- 若路灯编号 \(k\) 为奇数,则 \(k\) 和 \(3*k+1\) 相连。
- 若路灯编号 \(k\) 为偶数,则 \(k\) 和 \(\frac{k}{2}\) 相连。
现在已知路灯编号 \(pos\) ,输出 \(pos\) 和 \(pos+1\) 号路灯间的电线数量。
一共 \(T(1\leq T\leq 10^5)\) 组询问。
思考过程:
组内讨论时,推这道题的公式推的比较混乱,在提交一次WA了之后,经过与打表数据细致的比对,发现公式无法正确计算得出“3的奇数次倍数”的正确答案,于是对于这一部分数据进行了特判。代码一并给出在下方【AC代码2】中,供大家惊醒参考。
在赛后复盘中,我们重新推演了公式,得到了这道题的正解。
正解:
经组内讨论,发现答案由四部分组成:
- 位于 \(pos\) 号路灯之后的,编号为偶数的路灯,满足方程: \(\frac{x}{2} \leqslant pos\) 。
- 位于 \(pos\) 号路灯之前的,编号为偶数的路灯,满足方程: \(x\geqslant pos+1\) 。
- 位于 \(pos\) 号路灯之后的,编号为奇数的路灯,满足方程: \(x\leqslant pos\) 。
- 位于 \(pos\) 号路灯之前的,编号为奇数的路灯,满足方程: \(3*x+1\geqslant pos+1\) 。
于是题目化简为求满足\(\begin{cases}pos+1\leqslant x\leqslant 2*pos & \text{ ,x为偶数 } \\ pos\leqslant 3*x\leqslant 3*pos & \text{ ,x为奇数 } \end{cases}\)的 \(x\) 的数量。
由简单数理推断,发现当 \(pos\) 为偶数时,答案为 \(\frac{pos}{2}+(pos-2)\mid 3+1\) ;当 \(pos\) 为奇数时,答案为 \(\frac{pos+1}{2}+pos\mid 3+1\) 。
AC代码1:
//A WIDA Project
#include<bits/stdc++.h>
using namespace std;
long long q,pos,ans;
int main(){
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>q;
while(q--){
cin>>pos;
ans=0;
if(pos%2==0){
ans+=pos/2;
ans+=(pos-2)/3+1;
}else{
ans+=(pos+1)/2;
ans+=pos/3+1;
}
cout<<ans<<endl;
}
return 0;
}
AC代码2:
//team2699
#include<bits/stdc++.h>
using namespace std;
long long q,pos,ans;
int main(){
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>q;
while(q--){
cin>>pos;
ans=0;
if (pos%2==0){
ans+=pos/2;
ans+=((pos-1)-((pos/3)+1))/2+1;
}else{
ans+=(pos+1)/2;
ans+=(pos-((pos+1)/3+1))/2+1;
}
if(pos%3==0 && pos/3%2==1) ans++;//特判
cout<<ans<<endl;
}
return 0;
}
错误次数:2次
原因:公式推演存在纰漏
原因:误以为是输出格式有问题,更改输出之后再次提交试验
I. Command Sequence
tag:
⇔模拟、⇔数据结构
题意:
有一串只包含 \(UDRL\) 的字符串,代表机器人的行动指令串。现在要求输出满足要求的字串数量。
要求:使得机器人进行若干行动后仍返回原地。
一共 \(T(1\leq T\leq 20)\) 组询问。每串指令长度为 \(L(2\leq T\leq 10^5)\) 。
思考过程:
(王晨杰)使用数组模拟机器人移动。使用二维map数组优化空间。
设置初始位置为 \((0,0)\) ,且令 \(mp[0][0]=1\) ,此后,每次移动,令目标位置的数组值加1,再判断此时目标位置数组是否大于1,大于1说明存在满足条件的字串,满足条件的子串数量即为 \(mp[x][y]-1\) ,将其加到答案中。
模拟如下:
AC代码:
//team2699
#include<bits/stdc++.h>
using namespace std;
int q;
long long num;
char s;
void solve(){
cin>>n;
for(int i=0;i<n;i++){
cin>>s;
if(s=='D'){
mp[x][--y]+=1;
if(mp[x][y]>1) num+=(mp[x][y]-1);
}else if(s=='U'){
mp[x][++y]+=1;
if(mp[x][y]>1) num+=(mp[x][y]-1);
}else if(s=='R'){
mp[++x][y]+=1;
if(mp[x][y]>1) num+=(mp[x][y]-1);
}else if(s=='L'){
mp[--x][y]+=1;
if(mp[x][y]>1) num+=(mp[x][y]-1);
}
}
cout<<num<<endl;
}
int main(){
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>q;
while(q--){
int num=0,x=0,y=0;
map<int, map<int, int > > mp;
mp[0][0]=1;
solve();
}
return 0;
}
错误次数:1次
原因:大数测试的时候少打一个零,没测到最大数据导致爆int了
F. Power Sum
tag:
⇔数论(规律题)
题意:
对于给定的 \(n(1\leq n\leq 10^6)\) ,找到任意的一个 \(k\),满足
- \(1\leq k\leq n+2\)
- \(n\) 可以由“ \(1\) 至 \(k^2\) 的所有平方数”经过相加减计算后得到。
一共 \(T(1\leq T\leq 100)\) 组询问。保证 \(\sum{n}\leq 3*10^7\) 。
输出第一行为 \(k\) 的值,第二行为详细操作:对于\(1\) 至 \(k^2\) 的所有平方数,若减去平方数,则输出 \(0\) ,若加上,则输出 \(1\) 。
例如:
- \(4=-1^2-2^2+3^2\) 。\(k\) 即为3,详细操作为 \(001\) 。
- \(4=1^2-2^2-3^2+4^2\) 。\(k\) 即为4,详细操作为 \(1001\) 。
思考过程:
刚拿到这道题的时候,略微推了一下,立即感觉到了这是一道数论题,突破点在于找到规律。
于是我开始打暴力,对于每个 \(n\) ,都输出它的最小的 \(k\) 值。结果发现根本没规律,于是全队陷入停滞,导致我一度想直接用打表做(从1打到650多)。
直到后来后来重新审视了一遍前10个数字的全部数据,才终于找到规律,如下:
n | |||
1 | 1 | ||
2 | 0001 | ||
3 | 01001 | ||
4 | 1001 | ||
5 | 1 | \(\widehat{1001}\) | |
6 | 0001 | \(\widehat{1001}\) | |
7 | 01001 | \(\widehat{1001}\) | |
8 | 1001 | \(\widehat{1001}\) | |
9 | 1 | \(\widetilde{1001}\) | \(\widetilde{1001}\) |
10 | 0001 | \(\widetilde{1001}\) | \(\widetilde{1001}\) |
11 | 1001 | \(\widetilde{1001}\) | \(\widetilde{1001}\) |
… | … | … | … |
每四个数字为一组,组成规律。
AC代码:
//A WIDA Project
#include<bits/stdc++.h>
int n,T,X;
string s;
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
cin>>T;
for(int i=1;i<=T;i++){
cin>>n;
s.clear();
X=n%4;
if(X==1) s+="1";
else if(X==2) s+="0001";
else if(X==3) s+="01001";
else if(X==0) s+="1001";
X=(n-1)/4;
for(int x=0;x<X;x++) s+="1001";
cout<<s.size()<<"\n"<<s<<"\n";
}
return 0;
}
错误次数:1次
原因:一开始找规律的时候是将输出的字符串反过来看的(因为这样规律更显眼一点),最后输出的时候就没有多考虑,直接写了个for
循环取反,交了之后过了60分钟比赛结束了(土豆服务器,宕机4小时)才知道是超时,才意识到取反操作超时了,所以最后还是没能把这题A掉,有亿些可惜。
赛后小结
这场比赛我们团队发挥其实并不是很好。
在比赛前期,大家各自为营讨论思路,确定大致方向后确没有再做细致分析,没有统一团队思路,主副码手各自在思路存在分歧的情况下各自码题,导致比赛前半个小时团队较为混乱,第一题公式推演时出现重大纰漏,拖慢了全队进度。
比赛中期团队发挥尚可。
比赛进行到后期时,团队分工再次出现重大问题。我由于专心研究第三道(比赛顺序为第6题)数论题,在这期间未对团队策略进行明确评估,导致大家又出现了各自为营、各自开题的现象。以至于最后攻第三第四题都失败了,止步两题。作为队长,我在这段时间内存在较大失职,没能统筹各队员集中攻克一题,任大家各自发挥,双开两道题推进,导致比赛后三个小时团队效率极低。
补题计划与近期计划:
⇔数论、⇔规律题
一周五题+相应博客
Codeforces日常赛按照两场个人+一场团队的进度进行,尤其要注意团队赛的配合
【9月1日至9月4日】开始第二阶段集训
【九月每个周六周日(4、5、11、12、18、19、25、26)】ICPC各区域的预选赛
【时间未知】本次CCPC网络预选赛宣告作废,择日将进行重赛
【时间未知】CCCC大团队(10人)天梯赛