中南大学2019年ACM寒假集训前期训练题集(入门题)
A: 漫无止境的八月
Description
又双叒叕开始漫无止境的八月了,阿虚突然问起长门在这些循环中团长哪几次扎起了马尾,他有多少次抓住了蝉等等问题,长门一共回复n个自然数,每个数均不超过1500000000(1.5*10^9)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
Input
第1行是整数n,表示回复的自然数的个数。n<=1e6
第2~n+1行每行一个自然数。
Output
包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。
Sample Input
8
2
4
2
4
5
100
2
100
Sample Output
2 3 4 2 5 1 100 2
题意:给你n个数,你要找到输入的每个数出现了多少次,并从小到大的输出该个数对应的值和出现的次数。
解法:这题我们可以利用map来存储,我们知道map的key,value在输入进去在之后map会自动的以key值进行排序,所以我们利用这个性质,key存放对应的数值,value存放对应的次数,然后输出map就可以了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
int n;
map<int,int>m;
int main()
{
scanf("%d",&n);
m.clear();
int x;
while(n--)
{
scanf("%d",&x);
if(m.count(x)==0)
m[x]=1;
else
m[x]++;
}
map<int,int>::iterator iter;
for(iter=m.begin();iter!=m.end();iter++)
printf("%d %d\n",iter->first,iter->second);
return 0;
}
/**********************************************************************
Problem: 2204
User: jk1601zr
Language: C++
Result: AC
Time:148 ms
Memory:2424 kb
**********************************************************************/
B: Magia
Description
吼姆啦酱来救被变成魔女的纱耶香攻击的小圆辣!魔境背景中的指挥家指挥着这场表演的音乐,吼姆啦酱发现一个规律,如果过一串音符是回文的,那么这串音符会实物化来攻击她,现在给出一段音符,判断它是否是回文的。一个左右对称的自然数称为回文数,即这个数从左往右读与从右往左读是一样的,如121,686,13731,8668等都是回文数。
Input
输入一个int范围内的自然数N,判断它是否是回文数。如果是就输出这个回文数,若不是则输出-1。
Output
只有一行,N是回文数,就输出N,不是就输出-1。
Sample Input
686
Sample Output
686
题意:判断回文。
解法:直接存在字符串数组里面,感觉会方便比较吧,看个人习惯。然后区分奇数偶数对应的判断就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=1000;
char s[maxn];
int main()
{
scanf("%s",s);
int len=strlen(s);
bool flag=false;
if(len%2==1)
{
int temp=len/2;
for(int i=0;i<temp;i++)
{
if(s[i]!=s[len-i-1])
{
flag=true;
break;
}
}
if(flag)
printf("-1\n");
else
{
for(int i=0;i<len;i++)
printf("%c",s[i]);
printf("\n");
}
}
else
{
int temp=len/2;
for(int i=0;i<=temp;i++)
{
if(s[i]!=s[len-i-1])
{
flag=true;
break;
}
}
if(flag)
printf("-1\n");
else
{
for(int i=0;i<len;i++)
printf("%c",s[i]);
printf("\n");
}
}
return 0;
}
/**********************************************************************
Problem: 2205
User: jk1601zr
Language: C++
Result: AC
Time:4 ms
Memory:2024 kb
**********************************************************************/
C: 长门的运动会
Description
运动会,好开心~
CSU (California State University) 正在举行一场特殊的接力跑比赛,比赛在环形跑道上进行,同一支队伍的所有人从同一个位置向相同的方向出发,当需要接力的两个人再次相遇时,他们就要交接棒。最后总成绩是以队伍跑的总路程计算的。
现在接力的第一棒在Nagato手中,需要把它交给Kyon。在长度为C的环形跑道上,他们出发了!Nagato以速度A匀速跑动,Kyon以速度B匀速跑动。他们在经过多长时间后可以再次相遇?
Input
多组数据,第一行为一个整数T (1 ≤ T ≤ 106),表示数据组数。
之后每行是一组数据,有三个整数C, A, B (1 ≤ C, A, B ≤ 109, A ≠ B),分别表示环形跑道的长度,Nagato的速度和Kyon的速度。
Output
每行输出一个数,表示再次相遇所需的时间。绝对误差或相对误差小于10−5则认为是正确的。
Sample Input
2
3 1 2
5 10 7
Sample Output
3.00000000 1.66666667
题意:两个人从同一起点一起跑,看谁先比另一个人多跑一圈。
解法:求出两个人速度的差值,然后简单的物理计算。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=1000;
int T;
int c,a,b;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&c,&a,&b);
int temp=abs(a-b);
double ans=c*1.0/(temp);
printf("%.8f\n",ans);
}
return 0;
}
/**********************************************************************
Problem: 2158
User: jk1601zr
Language: C++
Result: AC
Time:316 ms
Memory:2024 kb
**********************************************************************/
D: 剪刀石头布
Description
现在一共有N个人(分别记为1, 2, …, N)在玩剪刀石头布,如果知道他们每个人都出了什么,你能找出来谁是winner吗?
当且仅当一个人可以赢其他所有人时,才称这个人是winner。
我们将剪刀记作2,石头记作0,布记作5,那么胜负关系就应当是2能赢5,5能赢0,0能赢2。
Input
输入数据的第一行包含一个整数T ( 1 <= T <= 150),表示接下来一共有T组测试数据。
每组测试数据的第一行包含一个整数N (2 <= N <= 100000)表示一共有N个人在玩剪刀石头布,接下来一行一共有N个数,每个数均为0、2或5中的某一个,依次描述了这N个人分别出了什么,其中第i个整数描述了第i个人出了什么。
Output
对于每组数据,用一行输出一个整数表示winner是第几个人([1, N]中的某个整数)。
如果不存在winner,则用一行输出“No winner”(不包括引号)。
Sample Input
3
3
5 5 2
3
2 0 0
3
0 2 5
Sample Output
3 No winner No winner
题意:模拟剪刀石头布的游戏,我们知道三个模式当且仅当出现两种,并且一个能打败另一个的时候才会有winner。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
const int maxn=100005;
int T;
int n,x;
//struct Node
//{
// int val;
// int cnt;
//};
int a[3],pos[3];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<3;i++)
a[i]=pos[i]=0;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
if(x==2)
{
a[0]++;pos[0]=i+1;
}
else if(x==0)
{
a[1]++;pos[1]=i+1;
}
else if(x==5)
{
a[2]++;pos[2]=i+1;
}
}
// if(a[0]!=0&&a[1]!=0&&a[2]!=0)
// printf("No winner\n");
if(a[0]==1&&a[1]==0)
printf("%d\n",pos[0]);
else if(a[1]==1&&a[2]==0)
printf("%d\n",pos[1]);
else if(a[2]==1&&a[0]==0)
printf("%d\n",pos[2]);
else
printf("No winner\n");
}
return 0;
}
/**********************************************************************
Problem: 1202
User: jk1601zr
Language: C++
Result: AC
Time:0 ms
Memory:0 kb
**********************************************************************/
E: 全场最水题之陈兴老师与比赛
Description
大家都知道ACM比赛罚时很重要。比如说你做A题要10分钟,B题要15分钟,如果先做A题再做B题,那么在ranking上的时间就是10 + (10)+ 15 = 35。如果先做B题再做A题总罚时就是15+(15)+
10=40.现在陈兴老师要做一场比赛,比赛有n道题, 总时间是300分钟。我们的陈兴老师仅仅看题目就可以知道他做每道题需要的时间。比如一般的比赛,陈兴老师做第一题需要1分钟,第二题2分钟,依此类推,陈兴老师只需要66分钟就可以AK一场11道题的比赛。PS: 陈兴老师做题都是1Y,膜拜陈兴老师Orz!
Input
第一行是一个数字n 0<n<=25
第二行是n个数字,第i个数字代表陈兴老师出编号为i的题所需要的时间 ti( 0 < ti <= 80)。
Output
第一行输出陈兴老师的出题数和Penalty(总时间)
以下按照顺序输出陈兴老师出题的顺序,每行一个编号。(详见输出样例)PS:时间一样的按编号升序输出。
Sample Input
3
1 2 3
4
1 2 3 4
6
60 60 60 60 60 60
Sample Output
3 10
1
2
3
4 20
1
2
3
4
5 900
1
2
3
4
5
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
struct Node
{
int t;
int num;
}node[30];
int cmp(Node a,Node b)
{
if(a.t!=b.t)
return a.t<b.t;
else
return a.num<b.num;
}
int main()
{
int n,i,j,sum,k;
while(cin>>n)
{
for(i=0;i<n;i++)
{
cin>>node[i].t;
node[i].num=i+1;
}
sort(node,node+n,cmp);
sum=0;k=0;
for(i=0;i<n;i++)
{
if(k+node[i].t>300)
break;
k+=node[i].t;
}
int temp1=i,temp2=i;
for(i=0;i<temp1;i++)
{
sum+=node[i].t*(temp2--);
}
cout<<temp1<<" "<<sum<<endl;
for(i=0;i<temp1;i++)
{
cout<<node[i].num<<endl;
}
}
return 0;
}
/**********************************************************************
Problem: 1315
User: jk1601zr
Language: C++
Result: AC
Time:320 ms
Memory:2024 kb
**********************************************************************/
F: 字符画
Description
读入 w,请输出 2018
的字符画,两个数字之间有 w 个空格。具体格式请参考样例输出。
- 1 ≤ w ≤ 2018
Input
输入文件只包含 1 个整数 w.
Output
输出 5 行,每行 12 + 3w 个字符(只包含 o
和 .
两种,字符画的部分用 o
,空格的部分用 .
),以换行符结尾。
Sample Input
2
Sample Output
ooo..ooo..ooo..ooo ..o..o.o...o...o.o ooo..o.o...o...ooo o....o.o...o...o.o ooo..ooo..ooo..ooo
直接模拟就行。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
int n;
int main()
{
scanf("%d",&n);
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
printf("\n");
printf("..o");
for(int i=0;i<n;i++)
printf(".");
printf("o.o");
for(int i=0;i<n;i++)
printf(".");
printf(".o.");
for(int i=0;i<n;i++)
printf(".");
printf("o.o");
printf("\n");
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("o.o");
for(int i=0;i<n;i++)
printf(".");
printf(".o.");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
printf("\n");
printf("o..");
for(int i=0;i<n;i++)
printf(".");
printf("o.o");
for(int i=0;i<n;i++)
printf(".");
printf(".o.");
for(int i=0;i<n;i++)
printf(".");
printf("o.o");
printf("\n");
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
for(int i=0;i<n;i++)
printf(".");
printf("ooo");
printf("\n");
return 0;
}
/**********************************************************************
Problem: 2163
User: jk1601zr
Language: C++
Result: AC
Time:8 ms
Memory:2024 kb
**********************************************************************/
H: joghs
Description
编号为1、 2、 3、 …、 n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。从指定编号为1的人开始,按顺时针方向自1开始报数,报到指定值m时停止报数,报第m的人出列,并将他的密码作为新的m值,从他在顺时针方向的下一个人开始,重新从1开始报数,如此类推,直至所有的人全部出列为止。输入n(n<=1000),m(m<=30000)及密码值(<=10000),试设计一个程序求出列顺序。
Input
有二行,第一行,N和M,第二行,N个小于等于10000的密码值,中间用空格隔开。
Output
只有一行,就是出列的顺序,编号间以空格隔开。
Sample Input
6 7
1 4 2 8 5 7
Sample Output
1 2 6 3 5 4
题意:约瑟夫环问题,但是要注意m值是在变化的,开始看题没注意。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <list>
using namespace std;
const int maxn=1005;
int n,m;
int a[maxn];
int main()
{
scanf("%d %d",&n,&m);
list<int>l;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
l.push_back(i);
}
list<int>::iterator it;
int cnt=1;
for(it=l.begin();l.size()!=1;)
{
if(cnt++==m)
{
printf("%d ",*it);
m=a[*it];
it=l.erase(it);
cnt=1;
}
else
it++;
if(it==l.end())
it=l.begin();
}
printf("%d\n",*l.begin());
return 0;
}
/**********************************************************************
Problem: 2053
User: jk1601zr
Language: C++
Result: AC
Time:24 ms
Memory:2028 kb
**********************************************************************/
G: N个数字求和
这题数据有锅,待补。
I: 英文单词
Description
编写程序,读入一行文本,文本是一个长度不超过255的英文句子,单词之间有一个或一个以上的空格,输出:
①统计单词的个数;
②一个对应的英文句子,其中原句中的所有小写字母均转换成大写字母,大写字母转换成小写字母;
③删除所有空格符后对应的句子。
Input
只有一行,就是一个英文句子
Output
有三行,第一行单词的个数,第二行,转换了大小写的英文句子,第三行删除空格的句子。
Sample Input
Who are you?
Sample Output
3 wHO ARE YOU? Whoareyou?
题意:直接模拟就行,但是要注意这个字符串的读入,要用到getline,不然空格读入不了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=300;
char s[maxn];
int main()
{
cin.getline(s,256);
int len=strlen(s);
// cout<<len<<endl;
int cnt=0;
for(int i=0;i<len;i++)
{
if(s[i]==' '&&((s[i+1]>='a'&&s[i+1]<='z')||(s[i+1]>='A'&&s[i+1]<='Z')))
cnt++;
}
if(s[0]!=' ')
cnt++;
printf("%d\n",cnt);
for(int i=0;i<len;i++)
{
if(s[i]>='a'&&s[i]<='z')
printf("%c",s[i]-32);
else if(s[i]>='A'&&s[i]<='Z')
printf("%c",s[i]+32);
else
printf("%c",s[i]);
}
printf("\n");
for(int i=0;i<len;i++)
{
if(s[i]==' ')
continue;
else
printf("%c",s[i]);
}
printf("\n");
return 0;
}
/**********************************************************************
Problem: 2050
User: jk1601zr
Language: C++
Result: AC
Time:4 ms
Memory:2024 kb
**********************************************************************/
J: Num
Description
编一程序,输入正整数N(N在2~32767之间), 求它的最大质因子(包括它本身)。
Input
只有一行,就是正整数N
Output
所求的最大质因子
Sample Input
7
Sample Output
7
题意:题面就很清楚了。
解法:预处理出2~32767所有的质数,然后从大到小对应的判断就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
const int maxn=323767;
set<int>s;
int check[maxn];
int n;
void init()
{
memset(check,0,sizeof(check));
for(int i=2;i<=maxn;i++)
{
if(!check[i])
s.insert(i);
for(int j=i+i;j<=maxn;j+=i)
check[j]=1;
}
}
int main()
{
init();
scanf("%d",&n);
for(int i=n;;i--)
{
if(s.count(i)&&n%i==0)
{
printf("%d\n",i);
break;
}
}
return 0;
}
/**********************************************************************
Problem: 2051
User: jk1601zr
Language: C++
Result: AC
Time:32 ms
Memory:4608 kb
**********************************************************************/
K: 时间旅行
Description
假设 Bobo 位于时间轴(数轴)上 t0 点,他要使用时间机器回到区间 (0, h] 中。
当 Bobo 位于时间轴上 t 点,同时时间机器有 c 单位燃料时,他可以选择一个满足 ⌈xh⌉⋅h≤c⌈xh⌉⋅h≤c 的非负整数 x, 那么时间机器会在 [0, x]中随机整数 y,使 Bobo 回到 (t − y) 点,同时消耗 y 单位燃料。 (其中 ⌈ ⋅ ⌉ 表示上取整)
因为时间机器的随机性,对于给出的参数 h 和时间机器剩余燃料 c,Bobo 想知道能够保证回到区间 (0, h] 中的 t0 的最大值。
- 1 ≤ h ≤ 109
- 0 ≤ c ≤ 109
- 数据组数不超过 105.
Input
输入文件包含多组数据,请处理到文件结束。
每组数据包含 2 个整数 h 和 c.
Output
对于每组数据输出 1 个整数表示 t0 的最大值。
Sample Input
100 99
100 100
100 149
Sample Output
100 101 150
模拟,读清题意就可以了。
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <list>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1.0);
const int MOD=10056;
const int maxn=2016;
int h,c;
int main()
{
while(scanf("%d %d",&h,&c)!=EOF)
{
if(h>c)
printf("%d\n",h);
else
printf("%d\n",c+1);
}
return 0;
}
/**********************************************************************
Problem: 2165
User: jk1601zr
Language: C++
Result: AC
Time:112 ms
Memory:2024 kb
**********************************************************************/