GDUT2016年ACM新生杯初赛题解

题目链接



Problem A: 贪吃的zhazhahe

Description

Zhazhahe很喜欢吃烧饼,但是要做好一块烧饼,要把两面都弄热,如果一次只能弄一个,zhazhahe一定会等得不耐烦,幸好现在有一个大的平底锅,一次可以同时放入k个烧饼,一分钟只能做好一面。而现在有n个烧饼,至少需要多少分钟才能全部做好呢?

Input

输入数据组数为T(T<=100),每组数据输入n和k,中间以空格隔开,其中1<=k,n<=1,000,000,000;

Output

对于每个测试样例,输出全部做好所需的最少分钟数。

Sample Input

2
1 1
3 2

Sample Output

2
3

HINT


/*
    分析:首先我们知道n个饼总的需要烤的面数是2*n,每次我们最多可以烤k面,
          所以烤的最小次数是2*n/k(整除时),或者2*n/k+1(不整除时,余数部分需要整体烤一次)
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
   int t;cin>>t;
   while(t--){
        int n,k;
        scanf("%d%d",&n,&k);
        if(n<=k){
            printf("%d\n",2);
            continue;
        }
        if(2*n%k!=0) printf("%d\n",2*n/k+1);
        else printf("%d\n",2*n/k);
   }
   return 0;
}
/**************************************************************
    Problem: 1196
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1696 kb
****************************************************************/


Problem B: 签到题

Description

某一天,北原春希、小木曾雪菜和冬马和纱分享幸福度。他们希望三人能平等获得这份幸福,否则他们就会各奔东西。于是叫你来判断他们能否三个人快乐的玩耍下去。

Input

输入数据为T组(T <= 100),每组数据读入一个幸福度n。(1<=n的位数<=500)

Output

对于每个测试实例,如果三人能平等获得幸福,则输出“Three people are the most stable”,否则输出“Why would it be like this”。双引号不用输出。

Sample Input

3
111111111
333333333333333333333333333333333333333333333
11111111111111111111111111111111111111111111

Sample Output

Three people are the most stable
Three people are the most stable
Why would it be like this

HINT


/*
    分析:把每一位加起来判断是否能够整除3即可。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 505;
char s[maxn];
int main()
{
    int t;cin>>t;
    while(t--){
        scanf("%s",s);
        int len=strlen(s);
        int sum=0;
        for(int i=0;i<len;i++){
            sum+=s[i]-'0';
        }
        if(sum%3)puts("Why would it be like this");
        else puts("Three people are the most stable");
    }
    return 0;
}
 
/**************************************************************
    Problem: 1197
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1696 kb
****************************************************************/


Problem C: 算罚时

Description

某次ACM比赛中你一次AC了全部8道题目,给出你AC每道题的时间,算出自己的罚时。

Input

输入数据为T组(T <= 100),每组数据读入8个时间,时间格式是HH:MM。每道题目的罚时为AC所用的分钟数。

Output

每组输出8道题的罚时之和。

Sample Input

3
00:00
00:00
00:00
00:00
00:00
00:00
00:00
00:00
05:00
05:00
05:00
05:00
05:00
05:00
05:00
05:00
00:30
01:00
01:30
02:00
02:30
03:00
03:30
04:00

Sample Output

0
2400
1080

/*
    分析:按照题意写就行了
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 505;
int main()
{
    int t;cin>>t;
    while(t--){
        int a,b,sum=0;
        for(int i=0;i<8;i++){
            scanf("%d:%d",&a,&b);
            sum+=a*60+b;
        }
        printf("%d\n",sum);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1198
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1696 kb
****************************************************************/


Problem D: 有趣的游戏

Description

有个小师妹找zhazhahe玩游戏。他们有一堆n个珠子,每人轮流拿走若干个,轮到谁的回合拿不了珠子就算输。给出一个n,每次能拿走的珠子数量在区间[l,r]内(如果剩余珠子不足就不能拿,判输),小师妹先开始拿。假设小师妹和zhazhahe都非常聪明,会采取最优策略,问谁会赢得游戏?

Input

有多组样例,第一行输入一个样例数T(0<T<=1000)

每个样例只有一行,三个正整数n,l,r (0<n<=1000) (0<l<=r<=1000)

Output

每个样例只有一行,如果小师妹赢了输出“Win”,输了就输出“Lose”。

Sample Input

3
4 1 4
7 2 6
10 3 6

Sample Output

Win
Win
Lose

HINT


/*
    类型:博弈
    分析:这种类型题的基本思路是找到一种恒定不变的方式,使得对方无论怎么拿,你都能找到对应要拿的数量
          举个例子,假如n=22,取的区间为[1,2],那么小师妹第一次拿走1个,
          使得剩下的数量21,是区间左右端点之和的倍数,即3的倍数.
          那么无论对方怎么拿,我们都能维持剩下来的数量是3的倍数的状态不变,比如他拿1个,你就拿2个,或者他拿2个,你就拿1个
          始终保持他能拿,我必能拿的状态,那么只要判断初始情况,我就知道我能不能稳赢
          回顾刚刚的拿法,我们很容易推出一个方式判断第一个人应该如何拿,即余数=n%(L+R)
          
          1.假设这个余数落在[L,R]里面,那么小师妹第一次把余数全抓走,剩下的是(L+R)的倍数,我们知道,小师妹稳赢
          
          2.假设这个余数为L-k (0<k<=L)里面,那么因为只能抓[L,R]个珠子,小师妹动不了余数这个数目,她只能先动(L+R)里面合法的某些数目,那么第二个人能对应着拿掉小师妹在(L+R)里面剩下的数目,情况变成小师妹稳输
          
          3.假设这个余数落在R+L-k (0<k<L)里面,那么小师妹第一次拿走R个,剩下的数目为L-k即把第二种状态丢给对方,小师妹稳赢
          
          所以题目可以解决.
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 505;
int main()
{
    int t;cin>>t;
    while(t--){
        int n,l,r;
        scanf("%d%d%d",&n,&l,&r);
        if(n%(l+r)<l)puts("Lose");
        else puts("Win");
    }
    return 0;
}
 
/**************************************************************
    Problem: 1199
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1696 kb
****************************************************************/


Problem E: 套套套

Description

矩形A能与矩形B不接触的放在矩形B里就称为矩形A能嵌套进矩形B。

给你n个矩形,编写程序,判断它们能否互不接触嵌套n层。

如:有2 * 2 , 4*5,3*4 三个矩形。

方案一嵌套非法,但是方案二合法(嵌套顺序任意),所以2*2,3*4,4*5满足条件

Input

第一行一个整数t(t < 15 ),表示有t组数据。 每组数据第一行一个整数n(n < 10000),矩形的个数,接下去的n行,每行两个正整数x和y(由空格分开),第i行表示第i个矩形的长为x和宽为y。(0 < y <= x < 100000 )

Output

每组数据输出一行,矩形能完成嵌套则输出“Yes”,否则输出“No”。(不包含双引号)

Sample Input

2
3
2 2
4 3
5 4
2
2 1
3 1

Sample Output

Yes
No

HINT

/*
    分析:因为题目限制了n个矩形要达到n层嵌套,所以对于n个矩形能否满足条件,
          我们只需要先对所有矩形的面积从小到大排序,再判断相邻两个矩形能否嵌入即可
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10000+5;
struct rt{
    ll x,y,s;
};
rt a[maxn];
bool cmp(const rt&a,const rt&b){
    return a.s<b.s;
}
int main()
{
    int t;cin>>t;
    while(t--){
        int n;scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%lld%lld",&a[i].x,&a[i].y);
            a[i].s=a[i].x*a[i].y;
        }
        sort(a,a+n,cmp);
        int flag=1;
        for(int i=1;i<n;i++){
            if((a[i].x>a[i-1].x&&a[i].y>a[i-1].y)||(a[i].x>a[i-1].y&&a[i].y>a[i-1].x))continue;
            else{
                flag=0;break;
            }
        }
        if(flag)puts("Yes");
        else puts("No");
    }
    return 0;
}
 
/**************************************************************
    Problem: 1200
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:8 ms
    Memory:1940 kb
****************************************************************/


Problem F: 吃豆豆

Description

在二进制下,十进制下的10写成1010,12可以写成1100。这个时候贪吃的Shadow把一些十进制下的数看成了二进制,并且把二进制中每一个1都看成了一颗豆豆,Shadow把这些十进制下的数字叫做豆数,Shadow想知道,他在每一个豆数中可以吃到多少颗豆豆。

Input

多组数据,对于每一组数据,有一个整数 n,代表豆数的值。最后以 -1结束输入。其中 0 <= n <= 1e18.

Output

对于每组数据输出一个整数,代表可以吃到的豆子数。

Sample Input

1012
-1

Sample Output

22

HINT


/*
    分析:判断一个数的二进制里面有几个1,不断对2取模和除2,看有几个满足即可
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10000+5;
int main()
{
    //int t;cin>>t;
    ll n;
    while(~scanf("%lld",&n)&&n!=-1){
        int sum=0;
        while(n){
            sum+=n%2;
            n/=2;
        }
        printf("%d\n",sum);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1201
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:8 ms
    Memory:1696 kb
****************************************************************/


Problem G: Pigofzhou和他的那么多个学妹

Description

男神pigofzhou在开学还没多久就基本上与16级几乎所有的师妹打成了一片,不过由于男生pigofzhou认识的师妹太多了,但是又怕忘了,于是就拿个本子记录下来,有一天他忽然想看一下这本本子有多少面,但是毕竟是pigofzhou怎么可能直接去数本子有多少面呢,于是对于每一页的页码都用键盘敲到电脑上,然后数自己敲了几次键盘,从而计算出本子有多少面,可以吧,这很pigofzhou,例如页码为1~9页,每页敲一下键盘,页码为10~99页,每页敲2下键盘,页码为100~999页,每页敲三下,以此类推。

Input

输入一个正整数t(0<t<3000)表示样例组数,每组样例输入一个正整数n(0<n<1e12),表示敲了n下键盘。

Output

输出一个正整数表示这本本子有多少面

Sample Input

5
9
11
15
23
39

Sample Output

9
10
12
16
24

HINT

虽然广工没那么多女生,但是数据并不小


/*
    分析:先预处理出第9、99、999、9999...页敲击键盘的次数,得到边界值,
    然后每次用边界值查找到n属于那个区域,再用n减去下界的次数得到从该区域第一个页数到当前页数的总敲击次数
    再用敲击次数求出该页数是在当前区域的第几个,再-1+10^数字的位数,就是答案
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10000+5;
ll a[15],p[15];//a储存边界值,p[i]表示10^(i-1)
int main()
{
    a[1]=9;p[1]=1;
    for(ll i=2,t=10;i<=13;i++,t*=10){
        a[i]=i*9*t+a[i-1];
        p[i]=t;
    }
    int t;cin>>t;
    while(t--){
        ll n;scanf("%lld",&n);
        for(int i=1;i<=13;i++){
            if(a[i]>n){
               printf("%lld\n",(n-a[i-1])/i-1+p[i]);
               break;
            }
        }
    }
    return 0;
}
 
/**************************************************************
    Problem: 1202
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1696 kb
****************************************************************/


Problem H: 神奇的清华大大的神奇魔法

Description

清华大大很喜欢字符串,因为在他眼中,字符串有关的题目都可以轻松解决。 但是清华大大不喜欢不是回文串的字符串,因为如果一个字符串是回文串,意味着清华大大只读一半的字符串就可以了。 回文串是前后读结果相同的字符串,例如"p”, "abba"是回文串,而“ac”,“yt”则不是。 如果遇到非回文串字符,神奇的清华大大就会施展神奇的魔法,每次他可以消耗1个魔法值将该字符串中的一个字母变成另一个字母,或者消耗0个魔法值改变该字符串中各个字母的顺序。 现在有一个字符串(只含小写字母),请你告诉清华大大该如何做才能施展尽可能少的魔法值使它变成回文串。

Input

第一行为T,有T个样例。小于50。 接下来每行含有一个字符串,每个字符串长度小于200000。

Output

每行输出消耗最少魔法值所产生的回文字符串, 如果有多个结果,输出字典序最小的结果

Sample Input

2
aabc
aabcd

Sample Output

abba
abcba

HINT


/*
    类型:贪心+模拟
    分析:先记录26个字母的出现次数num[],若num[i]为奇数,且只有一个字母,那么可以直接输出
          若存在多个num[i]为奇数
          这时分两种情况:
          1.需要把其它字母改为当前字母;
          2.把该字母改为其它字母。
          为了得到最小字典序,我们贪心的选择将字典序大的字母改为字典序小的字母,按照这样的思维模拟下去。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
const int maxn = 200000+5;
char s[maxn];
int a[30],n;
 
void print(){
    int flag=-1;
    for(int i=0;i<26;i++){
        if(a[i]%2)flag=i;
    }
    if(flag==-1){
        for(int i=0;i<26;i++){
            int len=a[i]/2;
            for(int j=0;j<len;j++){
                printf("%c",i+'a');
            }
            a[i]-=len;
        }
        for(int i=25;i>=0;i--){
            for(int j=0;j<a[i];j++){
                printf("%c",i+'a');
            }
        }
        puts("");
    }
    else{
        int cnt=0;
       for(int i=0;i<26;i++){
            int len=a[i]/2;
            for(int j=0;j<len;j++){
                printf("%c",i+'a');
                cnt++;
                if(cnt==n/2){
                    printf("%c",flag+'a');
                    a[flag]--;
                }
            }
            a[i]-=len;
        }
        for(int i=25;i>=0;i--){
            for(int j=0;j<a[i];j++){
                printf("%c",i+'a');
            }
        }
        puts("");
    }
 
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        memset(a,0,sizeof(a));
        scanf("%s",s);
        int len=strlen(s);
        n=len;
        for(int i=0;i<len;i++){
            a[s[i]-'a']++;
        }
        int flag=0;
        for(int i=0;i<26;i++){
            flag+=a[i]%2;
        }
        if(flag<=1)print();
        else{
            int k=26;
            while(k--){
                //flag=0;
                int r=-1,l=-1;
                for(int i=25;i>=0;i--){
                    if(a[i]%2){
                        if(r==-1){
                            r=i;
                            break;
                        }
                    }
                }
                for(int i=0;i<25;i++){
                    if(a[i]%2&&l==-1){
                        l=i;
                        break;
                    }
                }
                if(l!=r){
                    a[r]--;
                    a[l]++;
                }
            }
            print();
        }
    }
    return 0;
}
 
 
/**************************************************************
    Problem: 1203
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1896 kb
****************************************************************/


Problem I: 神枪手TMK

Description

TMK十分喜欢打CS,据说GDUTACM新生杯的一等奖的奖品的星际CS的真人CS游戏团体券,他毅然报了名。 在新生杯的初赛上,TMK被一道题卡住了,然后TMK居然。。。。。睡着了,他梦做了一个很长的梦,他梦见了自己进入了宇宙空间,忽然一班外星人向TMK袭来,TMK在用聪明的头脑打败了一个外星人后,成功的夺得了外星人的一把枪,TMK是个神枪手,他每次开枪都能把两个外星人干掉。 新生杯结束后,yfq摇醒了TMK,TMK虽然醒了,但他还在回味之前的梦,他想知道自己干掉了多少个外星人,但他记不清了,他只记得自己开了多少次枪。TMK很不开心,于是yfq想帮帮他算一下他干掉了多少外星人。

Input

题目包含多组数据 对于每一组数据,输入有一个数字n(-10000<=n<=10000),表示tmk一共开了多少次枪。

Output

对于每组数据,输出一行,如果不能可能有这种情况,那么肯定是tmk记错了,输出”impossble”(不带引号),否则输出有一个数字x,表示tmk一共干掉了多少外星人

Sample Input

3260-1

Sample Output

75131impossble

HINT


/*
    分析:直接写把
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
const int maxn = 200000+5;
 
int main()
{
    //int t;cin>>t;
    int n;
    while(~scanf("%d",&n)){
        if(n<0)puts("impossble");
        else printf("%d\n",2*n+1);
    }
    return 0;
}
 
 
/**************************************************************
    Problem: 1204
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1696 kb
****************************************************************/


Problem J: 神龙的烦恼

Description

冰法师zz因为苦修寒冰魔法而耽误了找女朋友的大事,于是他集齐了7颗龙珠,召唤出了神龙。 神龙:说出你的愿望吧。 zz:我想要一个漂亮又闻名世界,会各种姿势而且绝不会跟我闹别扭的妹子做我女朋友。 神龙:这好办。 于是乎,一个芭蕾娃娃人偶从天而降,神龙消失在天际。 最近太多宅男向神龙许愿要女朋友了,这要让神龙准备多少个芭比娃娃啊。神龙累了,于是他找到了你,希望你帮忙算一它购置m个芭比娃娃的费用。现有n个供货商,第i(1<=i<=n)个供货存芭比娃娃量amount[i],单价cost[i]。由于向神龙许愿要钱的人也很多,所以神龙希望花费金额数最少,请你告诉它最少需要用多少钱买芭比娃娃。 若供货商无法提供出m个芭比娃娃,则输出-1。

Input

第一行有两个整数n,m(1<=n<=10^6,m<=10^8),分别代表供货商数量和神龙要买的芭比娃娃数量。 第二行到第n+1行均有两个整数amount[i],cost[i](1<=amount[i],cost[i]<=10^6)分别代表第i个供货商所存芭比娃娃数量和芭比娃娃的单价.

Output

仅有一个整数ans,代表神龙最少花费金额,或者是-1,代表买不到m个芭比娃娃。

Sample Input

5 201 14 5010 64 205 8

Sample Output

181

HINT


/*
    分析:价格从小到大买就行了
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
struct babi{
    ll num,val;
};
babi a[maxn];
bool cmp(const babi&a,const babi&b){
    return a.val<b.val;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    ll sum=0;
    for(int i=0;i<n;i++){
        scanf("%d%d",&a[i].num,&a[i].val);
        sum+=a[i].num;
    }
    if(sum<m)puts("-1");
    else{
        sort(a,a+n,cmp);
        sum=0;
        for(int i=0;i<n;i++){
            if(a[i].num<m){
                sum+=a[i].val*a[i].num;
                m-=a[i].num;
            }
            else{
                sum+=a[i].val*m;
                break;
            }
        }
        printf("%lld\n",sum);
    }
 
 
    return 0;
}
 
 
/**************************************************************
    Problem: 1205
    User: MDZZhhh
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:0 kb
****************************************************************/



  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值