中南大学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 单位燃料时,他可以选择一个满足 xhhc⌈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
**********************************************************************/

 

posted @ 2018-12-10 14:11  从让帝到the_rang  阅读(1246)  评论(0编辑  收藏  举报