2021中国大学生程序设计竞赛(CCPC)网选赛(第一场)
总结:本次比赛,打的差的一塌糊涂,为了一道签到题甚至用了5个小时(最悲剧的是还没做出来),隔壁学弟都比我这个老油条强了,哎。
1001 Cut The Wire
前言(唠嗑):本题全靠我万能的队友做的
Problem Description:
In the country of Infinity , there is a strange road. This road only has a starting point, but no end. Since this road is infinite, there are also countless street lights. The street lights are numbered from 1(the starting point) to infinity. The street lights are connected by wires under a strange law:
For a street light x,
if x is even, then x is connected with x2 by a wire;
if x is odd, then x and 3x+1 is connected by a wire.
Now Kris is standing in the middle of street light n and n+1, and he is able to cut all wires passing by. That is, he will cut all wires connecting street lights a and b satisfying a≤n and b>n.
Now he wonders, how many wires he will cut. Please help him calculate.
Input:
This problem contains multiple test cases.
The first line contains an integer T(1≤T≤105) indicating the number of test cases.
The next T lines each contains one integer n(1≤n≤109).
Output:
For each test case, output one line of one integer indicating the answer.
Sample Input:
2
12
60
Sample Output:
10
50
题意:
有一个无限长的x正整数轴,轴上每个点都代表一个路灯,路灯由电线连着。
对于第x盏路灯,如果x是奇数,那么他(x)和第 3x+1 盏路灯相连;如果x是偶数,那么他(x)和第 x / 2 盏路灯相连。
你现在站在第n和n+1的路灯之间,经过你的电线你可以一刀切断,也就是说当两盏能够相连的路灯a,b满足a<=n且b>n就算做一条经过你的电线,求你能斩断多少条电线
思路:
其实理解了题意就会了,以n为界限,如果i<n,那么i就不可能是偶数(i和i/2必定小于n,电线过不来),如果i>n,那么i就不能是奇数(i和3i+1必大于n,电线也过不来)
那么,这题就是求当i<n时,i为奇数的最小值到n之间的奇数个数;当i>n时,i为偶数到i*2之间的偶数个数。两者相加就是答案
下面展示一些 内联代码片
。
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int INF=100000000;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
int ans=0;
cin>>n;
if(n%2==0)//分情况讨论,如果n是偶数的话
{
ans+= (n/2);//n右边只能是偶数才能切,偶数个数是(终点-n)/2由于终点=n*2,所以简化算式就是n/2
int temp=0;
temp=(n/3);//n左边只能是奇数,而奇数必须有个起点,当n是偶数时起点就是先n/3就行
if(temp%2==0) temp=temp+1;//如果起点是偶数就向上取一个奇数
else temp=temp+2;//如果起点算出是奇数,由于3x+1>=n+1向上取整,所以+2
ans+=((n+1)-temp)/2;
}
else//如果n是奇数
{
ans+=(n+1)/2;//当n是奇数,右边偶数的个数
int temp=0;
temp=ceil((double)n*1.0/3);//n是奇数,求起点,向上取整后
if(temp%2==0) temp=temp+1;//如果起点是偶数+1变成奇数,如果是奇数那就是起点
ans+=((n+1)-temp)/2;
ans+=1;//加上n与3n+1这一条线
}
cout<<ans<<endl;
}
return 0;
}
1006 Power Sum
前言(唠嗑):怎么说呢这题是打完之后问学长才明白的,这题也是队友去思考的,当时看了一下题目,觉得下不去手,就去做09了
题目:
Given a positive number n, Kris needs to find a positive number k and an array {ai}(ai∈{−1,1}) of length k(1≤k≤n+2), such that:
This is too hard for Kris so you have to help him.
Input:
The input contains multiple test cases.
The first line contains an integer T(1≤T≤100) indicating the number of test cases.
Each of the next T lines contains one integer n(1≤n≤106).
It’s guaranteed that ∑n≤3∗107.
Output:
The output should contain 2T lines. For each test case, output two lines.
The first line contains one integer, k.
The second line contains a 01-string of length k representing the array, with 0 in the ith position denoting ai=−1 and 1 denoting ai=1.
If there are multiple answers, print any.
Sample Input
2
1
5
Sample Output
1
1
2
11
题意:给出1-k(k<=n+2)的平方,每个数的要么是负(-)要么是正(+)最后使得他们相加之和等于一个n
思路:
就是一道找规律的题目,只要找到规律,你就是无敌的,本题的规律是任意4个数如果他的符号是±-+的话,他的最终解都为4。那么我们利用这点只要计算出1 2 3所需要的就行了(这题找到规律后 巨简单,就一水题)
下面展示一些 内联代码片
。
#include<iostream>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n, remain = 0, group = 0;
cin>>n;
remain = n % 4;//还需要多少等于n
group = n / 4;//需要多少(k)组"1001"
if(remain==0){
for(int i=0;i<group;i++){
cout<<group*4<<endl;//长度k*4
cout<<"1001";
}
cout<<endl;
}
if(remain==1){
cout<<group*4+1<<endl;
cout<<"1";
for(int i=0;i<group;i++){
cout<<"1001";
}//长度k*4+1
cout<<endl;
}
if(remain==2){
cout<<group*4+4<<endl;
cout<<"0001";
for(int i=0;i<group;i++){
cout<<"1001";
}//长度k*4+4
cout<<endl;
}
if(remain==3){
cout<<group*4+2<<endl;
cout<<"01";
for(int i=0;i<group;i++){
cout<<"1001";
}//长度k*4+2
cout<<endl;
}
}
return 0;
}
1009 Command Sequence
前言(唠嗑):这道题出最后答案的时候,才发现自己是真的蠢,我想了各种方式去找,甚至去画了例子,还有自己的例子的图,硬生生没找到有啥规律(菜),最后去问学长才知道的(程序竞赛,菜是原罪)
Problem Description:
There is a robot that can move by receiving a sequence of commands.
There are four types of command in the command sequence:
U: robot moves one unit up.
D: robot moves one unit down.
L: robot moves one unit left.
R: robot moves one unit right.
Now, given a command sequence of length n. You need to find out how many substrings of the command sequence satisfy that if the robot execute the substring command, it can return to the starting position.
A substring is a contiguous sequence of characters within a string. For instance, “the best of” is a substring of “It was the best of times”. For example, “Itwastimes” is a subsequence of “It was the best of times”, but not a substring.
Input:
This problem contains multiple test cases.
The first line contains an integer t (1≤t≤20) indicating the number of test cases.
For each test case, the first line contains one integer n (2≤n≤105).
The second line contains a UDLR string of length n.
Output
For each test case, output one line one integer indicating the answer.
Sample Input
1
6
URLLDR
Sample Output
2
题意:
一个机器人能上,下,左,右走,问里面他有多少 个子字符串能够回到初始的起点
思路:
设置向右走是+1,左是-1,上是+3x105,下是-30x105,执行一次命令就把结果存起来,最后数相同的数字可以组合多少,把每组相同数的组合数加起来就是答案
如果两个数相同,我们可以把它们看成是起点0,不管它们中间怎么走,最后都回到了0起点
如果用纯数组去做然后求n*(n+1)/2会很麻烦,可能会发生例如:3005这个数最后经过3次,但顺序处理数组可能会把他为2时的数据一起存入,导致结果偏大
所以我们选择用map去代替计算n*(n+1)/2
#include<iostream>
#include<map>
using namespace std;
map<long long,long long>pos;
const int maxn = 1e6;
char rob[maxn];
int main()
{
int t;
cin>>t;
while(t--){
int n, value = 0;//value把字符转换为数字形式
long long ans = 0, sum = 0;
cin>>n;
for(int i=0;i<n;i++){
cin>>rob[i];
}
pos.clear();
pos[0] = 1;
for(int i=0;i<n;i++){
if(rob[i]=='U') value = 3e5;
if(rob[i]=='D') value = -3e5;
if(rob[i]=='R') value = 1;
if(rob[i]=='L') value = -1;
sum += value;//累加
ans += pos[sum];//如果这个数第一次出现就开辟出来,初始值为0
pos[sum] += 1;//这个点经过一次
}
cout<<ans<<endl;
}
return 0;
}
当时就硬生生的在设置上下走动为1,左右步行为1,然后发现根本难以下手。
总结:打ccpc打到现在,签到题都要开运气做的憨批(为自己的未来堪忧中。。)