湖南中医药大学2017年集训队第五场选拔赛

来源:互联网 发布:普通pc安装mac系统 编辑:程序博客网 时间:2024/04/28 13:54

Problem A: Press the switch

Problem A: Press the switch

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 310 Solved: 78
[Submit][Status][Web Board]
Description

达达的家里有一串长度为n的灯泡,编号1,2,3,4…..n-1,n。每一个灯泡都有一个开关,达达每次选一个数a,把编号为a的倍数的灯泡的开关都按一遍。
假定灯刚开始都开着,他做了m次这样的事,问他爸妈打他没有?偶,不不不,问最后有几个灯开着。
Input

多组测试数据,第一行输入一个n(1<=n<=1e12)

第二行数输入一个数m(0<=m<=2)

接下来输入m个数ai(1<=ai<=min(1000,n))

Output

输出最后结果

Sample Input

100
1
2
5
2
2 3
100000000000
1
1
Sample Output

50
2
0

[分析]
这题交了无数次才a,真的是一路坎坷。
n超级大,一看见这个当时心里就有点凉了,感觉自己不会做。但是看见m只有0到2,瞬间就明白了,这就是一个数学问题。

当m=0,直接输出n,因为没有灯被关。

当m=1,输出n-n/a1,n/a1就是所有a1的倍数的个数。所有关掉a1的倍数灯为n-n/a1;

麻烦就在m=2;
因为减去a1倍数和a2倍数后会出现某几个灯被重复关。
那么这些重复的灯有多少呢,一开始我以为是n/(a1*a2);
所以m=2的式子是n-n/a1-n/a2+n/(a1*a2);
交上去wa了。几番修改,提交,测试,发现一组数据100 20 5输入时答案不对。
发现重复的灯个数应该是lcm(a1,a2)(a1和a2的最小公倍数)。
所以m=2的式子是n-n/a1-n/a2+n/lcm(a1*a2);
依旧wa,内心是绝望的。又是几番测试发现,其实很简单,因为是重复关闭,所以要+2n/lcm(a1,a2);
于是ac了。

[代码]

#include<cstdio>long long gcd(long long a, long long b)//最大公约数{    return b ? gcd(b, a%b) : a;}long long lcm(long long a, long long b)//最小公倍数{    return a / gcd(a, b)*b;}int main(){    long long n,m,a1,a2;    while(scanf("%lld",&n)!=EOF)    {        scanf("%lld", &m);        if (m == 0)printf("%lld\n", n);        else if (m == 1)        {            scanf("%lld", &a1);            printf("%lld\n", n - (n / a1));        }        else if (m == 2)        {            scanf("%lld%lld", &a1, &a2);            printf("%lld\n", n - (n / a1) - (n / a2) + 2*(n / lcm(a1,a2)));        }    }}

Problem B: 寻找倍数

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 163 Solved: 97
[Submit][Status][Web Board]
Description

给出n(n<=10000)个正整数,每个数xi<=15000.可以在这个n个数中选择一些数出来,至少选择一个,是否存在一种选择方案使得选择出
来的数的和是n的整数倍
Input

第一行一个T(T<=500),第二行一个数n,接下来n个正整数

Output

Case #x: y,其中x是测试编号,从1开始,y表示答案,如果存在y为Yes,否则为No

Sample Input

2
5
1 2 3 4 1
2
1 2
Sample Output

Case #1: Yes
Case #2: Yes

[分析]
很邪门,就是感觉不可能不是,居然A了。。。。玄学。。
之后研究

[代码]

#include<cstdio>int main(){    int t,x;    scanf("%d", &t);    int kase = 0;    while (t--)    {        int n;        scanf("%d", &n);        for (int i = 0; i<n; i++)        {            scanf("%d", &x);        }        printf("Case #%d: Yes\n", ++kase);    }    return 0;}

Problem C: 分钱哪

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 297 Solved: 85
[Submit][Status][Web Board]
Description

生活在杭州,大家是不是习惯了出门只带一只手机就好啦,无论是大商场还是街边小摊都能用上支付宝,不得不说真是方便呀,知识改变命运,科技改变生活,代码改变世界,每当放假回家,我就回到了没有支付宝的地方了,然后,就要使用人民币啦,麻烦的是大部分情况下是要找零,为了不找零,于是我决定事先做好准备,我把钱数好,然后放在一个个钱袋里面,以便在我现有的支付能力下,任何数目的钱,我都能够使用我事先准备好的小钱进行支付。当然,我很穷所以我想用最少的钱袋来实现这个愿望,并且不存在两个钱袋中装有相同的大于1的钱数。假设我有m个1元硬币,你能猜到我会用多少个钱袋?
Input

第一行T(T<=1000000),接下来一个整数,表示我现有的总的硬币数目m,其中,1≤m ≤1000000000
Output

Case #x: y,x表示测试编号从1开始,y一个整数表示答案

Sample Input

2
3
4
Sample Output

Case #1: 2
Case #2: 3

[分析]
没找到规律的时候开大数组各种循环很难受wa了,然后测试的时候循环输出了1到100,发现其实袋数相同的个数是前一个的两倍,如何就很开心了(case真是个好东西)

[代码]

#include<cstdio>using namespace std;int main(){    int t, m,kase=0;    scanf("%d", &t);    while(t--)    {        int ans = 0;        scanf("%d", &m);        while (m)         {            m = m / 2;            ans++;        }        printf("Case #%d: %d\n", ++kase, ans);    }    return 0;}

Problem D: 无法言表

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 216 Solved: 84
[Submit][Status][Web Board]
Description

给出N个数,要求把其中的重复的去掉,只保留第一次出现的数.1 <= N <= 50000,给出的数在32位有符号整数范围内。

Input

第一行T(T<=10),接下来一个数n,接下来n个数

Output

Case #x: y1,y2,…,x是测试编号从1开始,y_i表示答案

Sample Input

2
11
1 2 18 3 3 19 2 3 6 5 4
6
1 2 3 4 5 6
Sample Output

Case #1: 1 2 18 3 19 6 5 4
Case #2: 1 2 3 4 5 6

[分析]
水题,用map,代码看一下一般就懂了(其实用set就可以了,我一直没学)

[代码]

#include<cstdio>#include<map>using namespace std;int main(){    int t;    int kase = 0;    map<int, int>mp;    scanf("%d", &t);    while(t--)    {        mp.clear();        int n,x;        scanf("%d", &n);        printf("Case #%d:", ++kase);        while(n--)        {            scanf("%d", &x);            if (mp[x] == 0)            {                mp[x] = 1;                printf(" ");                printf("%d", x);            }        }        printf("\n");    }}

Problem G: 艰难的起床

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 215 Solved: 122
[Submit][Status][Web Board]
Description

冬天最令人讨厌的事情就是起床吧!达达每天都要早起去上班,所以他就会定一个闹钟,闹钟一响他就会起床。
但是由于被子的封印结界太强,直接起床是不可能的。达达和被子长期战斗,有了丰富的经验,被子的封印每隔10分钟就会削弱1。
现在告诉你达达的闹钟时间T1,和起床时间T2,能否求得被子的最大可能封印能力。
Input

多组测试数据。
输入T1,T2。多组测试数据。
保证T2时刻在T1之后,并且是同一天的时间。
Output

输出结果。

Sample Input

7:00 7:10
7:00 7:11
7:33 8:30
Sample Output

1
1
5
[分析]
水。

[代码]

#include<cstdio>int main(){    int h1, m1,h2,m2;    while (scanf("%d:%d %d:%d", &h1, &m1, &h2, &m2) != EOF)    {        int time1 = h1 * 60 + m1;        int time2 = h2 * 60 + m2;        int time = time2 - time1;        printf("%d\n", time / 10);    }}
阅读全文
0 0