2017-AHU校赛网络赛解题报告

来源:互联网 发布:淘宝校园卡 编辑:程序博客网 时间:2024/06/05 20:45

E题的网络流还不会,先放着。由于打网络赛的时候在南京玩,随便找了家网吧做了前面几题,后面的几题由于比赛结束还没有放到OJ上评测,但都和AC的代码对拍100项以上没问题的,不出意外都能A。(这是个flag···)

A.成功人士

题面:

Description
学校里共有n个学生,m门课,如果某个学生在某门课中拿到了最高分(可以是并列),则这个学生是成功人士。现在给出n个学生的m门课的成绩,问有多少个成功人士。

Input
第一行,一个整数t,表示测试数据组数,(1<=t<=100)
对于每组测试数据,第一行两个整数,n和m,(1<=n,m<=50)
接下来n行,每一行有m个数字(中间不分隔),表示这个学生每门课的成绩,其中成绩为1-9的整数。

Output
每组测试数据,一个整数,表示有多少个成功人士。

Sample Input
2
3 3
223
232
112
3 5
91728
11828
11111

Sample Output
2
3

思路:

在第一次循环读入成绩的时候,得出每一门的最高成绩并记录。之后再扫一遍数人数就行了。

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef struct {    char grade[60];//由于题面上各个成绩之间没有空格,所以干脆用字符串进行处理} Stu;int main(){    int m,n,t;    Stu student[60];    cin>>t;    while(t--)    {        char maxn[60];        memset(maxn,'0',sizeof(maxn));        memset(student,0,sizeof(student));        cin>>n>>m;        for(int i=0;i<n;++i){            for(int j=0;j<m;++j){                cin>>student[i].grade[j];                if(student[i].grade[j]>maxn[j])                    maxn[j]=student[i].grade[j];            }        }        int ans=0;        for(int i=0;i<n;++i){            for(int j=0;j<m;++j){                if(student[i].grade[j]==maxn[j]){                    ans++;//找到一个记录后记得跳出这一层循环,因为不管一个人的成绩有多少门第一,都只能算一次。                    break;                }            }        }        cout<<ans<<endl;    }    return 0;}

B.迭代归一

题面:

Description
我们把一个正整数的每一位上的数字加起来,得到新的数字,我们把这样的一次操作称为一次迭代变换。直到这个数字只有一位数。
如,9876经过一次变换成为9+8+7+6=30,经过第二次变换成为3+0=3,结束。
那么9876就经过了两次迭代变换。如今给一个正整数,问需要迭代变换多少次后会停止。

Input
一个整数t,表示测试数据组数(1<=t<=100)。
对于每组测试数据,只有一行,表示一个正整数,正整数最多有100000位。

Output
输出若干行,每行对应每组数据需要迭代变换的次数

Sample Input
3
2
10
99999999

Sample Output
0
1
2

思路:

由于正整数比较大,所以用数组进行保存。但处理过一次就不需要了,拿int存就够了。
纯模拟题,按题意敲就行了。

代码:

#include<iostream>#include<cstring>#include<cstdlib>using namespace std;int main(){    int t;    cin>>t;    while(t--)    {        char number[100000];        memset(number,0,sizeof(number));        cin>>number;        long long a=0,b=0;//比赛的时候以防万一用的是long long,但其实int应该也够了        int len=strlen(number);        if(len==1){            cout<<"0"<<endl;            continue;        }        int ans=1;        for(int i=0;i<len;++i)             b+=number[i]-'0';//转化为数字        while(b>=10)        {            int a=0;            while(b>0)            {                a+=b%10;                b/=10;            }            b = a;            ans++;        }        cout<<ans<<endl;    }    return 0;}

C.置换的魔术

题面:

Description
有n个正整数,其中1到n的正整数出现且只出现一次的序列,称为1-n的一个排列。
如1,2,3和3,1,2都是1-3的排列,但是1,3,3不是1-3的排列。
如今,给n个数,问最少修改几个数,可以使得序列成为1-n的一个排列。

Input
一个整数t,表示测试数据的组数,(1<=t<=210)
对于每一组测试数据,第一行为一个整数n,(1 <= n <= 500)
第二行有n个整数a1,a2,……an,空格分隔,(ai为任意的32位有符号正整数)。
保证多组数据中的n的和不超过100000。

Output
每组测试数据,输出一个整数,表示最少修改几个数。

Sample Input
2
5
1 3 2 4 5
6
1 1 1 1 1 1

Sample Output
0
5

思路:

给的数有可能是负数或者是大于n的数,要小心。
用一个bool数组标记一下,最后扫一遍计数应该就可以了。

代码:

#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>using namespace std;int main(){    int T;    cin>>T;    while(T--)    {        int n;        int a[510];        bool flag[510];        memset(flag,true,sizeof(flag));        cin>>n;        for(int i=0;i<n;++i){            cin>>a[i];            if(a[i]>0&&a[i]<=n)//控制数据范围                flag[a[i]]=false;        }        int cnt=0;        for(int i=1;i<=n;++i){            if(!flag[i])                cnt++;        }        cout<<cnt<<endl;    }    return 0;}

D.买买买

题面:

Description
一天Alice打开了她日常玩的游戏,发现她里面还有n个游戏币,她想把这些游戏币花光。
现在可以买的一共三种道具,分别是房子(每一个价值1234567个游戏币),车子(每一个价值123456个游戏币),电脑(每一个价值1234个游戏币)。
现在她想知道,通过买这三种道具是否可以把n个游戏币全部花光。

Input
第一行,一个数字t(1<=t<=100)。代表测试数据数量。
对于每一组测试数据,一个整数n(1<=n<=1000000000),代表现在的游戏币。

Output
输出n行,每行输出”YES”或者”NO”,表示她可以或者不可以把游戏币全部花光。

Sample Input
2
1359257
17851817

Sample Output
YES
NO

思路:

由于车,房子的价值都很大,所以能用枚举逐个尝试。然后把剩下的钱看对于电脑的钱取%,看是否为零就行了。

代码:

#include<iostream>#include<cstdlib>#define HOUSE 1234567#define CAR 123456#define COM 1234using namespace std;int main(){    cin.sync_with_stdio(false);    int T;    cin>>T;    while(T--)    {        bool flag=false;        long long n;        cin>>n;        int mh=n/HOUSE;        for(int i=0;i<=mh;++i){            int mcar=(n-i*HOUSE)/CAR;            for(int j=0;j<=mcar;++j)                if((n-i*HOUSE-j*CAR)%COM==0){                    flag=true;                }            if(flag)                break;        }        if(flag)            cout<<"YES\n";        else            cout<<"NO\n";    }    return 0;}

F.周末大法好

题面:

Description
在火星上,每年有x天。惊奇的是,和地球上一样,火星上也是有星期的概念的,连续的5天工作日,然后连续的2天周末。他们只有周末放假。
现在你的任务是,确定火星上每年可能的最少放假的天数和最多放假的天数。

Input
第一行,一个数字n。代表测试数据数量。
接下来n行,每行一个整数x (1<=x<=1,000,000),代表火星每年有x天。

Output
输出n行,每行两个整数。代表火星上每年可能的最少放假的天数和最多放假的天数。

Sample Input
2
14
2

Sample Output
4 4
0 2

思路:

先把一年天数除以7乘以2,这是最少的放假天数。
然后一年天数对7取%,剩下的如果是6,则最少天数还要再加一。
而最多的天数应该是至少的放假天数加上min(一年天数%7,2),因为如果只剩下一天了,最多只能放假一天。而其他情况则可以是在一年开头多过一个周末(也就是两天)

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int main(){    int t;    cin>>t;    while(t--)    {        int x;        cin>>x;        int  Min=x/7*2,Max;        int  mod=x%7;        if(mod==6)            Min++;        Max=x/7*2+min(mod,2);        cout<<Min<<" "<<Max<<endl;     }    return 0;}

G. 交换大法好

题面:

Description
有一天,天上掉馅饼了。不过不是直接掉馅饼,是告诉你你将要得到的馅饼的数量a。聪明的你得到了一种魔法,可以在整数a中交换任意两个相邻的数字。而这种魔法,你最多只能使用k次。你使用魔法操作a,得到的最大的结果就是你最终获得的馅饼数量。

你最多可以获得的馅饼数量是多少呢?

Input
第一行,一个数字n(1<=n<=60)。代表测试数据数量。
接下来n行,每行两个整数a和k(1<=a<=1,000,000,000; 0<=k<=100)。

Output
输出n行,每行一个整数,代表你最多使用魔法k次,可以得到的最大的数字。

Sample Input
2
1990 1
1034 2

Sample Output
9190
3104

思路:

暴力找

代码:

#include<iostream>#include<cstring>#include<cstdlib>using namespace std;void swap(char *a,char *b){    char t=*a;    *a=*b;    *b=t;}int main(){    int T;    cin>>T;    while(T--)    {        char s[20];        int k;        cin>>s>>k;        int len=strlen(s);        if(len==1){            cout<<s<<endl;            continue;        }        char Max='0';        int Maxid=-1;        for(int i=0;i<len;++i){            if(k<=0)                break;            Max = s[i]; Maxid = i;            for(int j=i;j<=i+k&&j<len;++j){                if(s[j]>Max){                    Max=s[j];                    Maxid=j;                }            }            k-=Maxid-i;            for(int x=Maxid;x>i;--x)                swap(&s[x],&s[x-1]);        }        cout<<s<<endl;    }    return 0;}

H. 今年多少岁

题面:

Description
小明出生于1937年7月7日,问对于给定的日期,小明几周岁了,不足一周年的部分可以忽略。
注意:1938年7月6日,小明0周岁,1938年7月7日小明1周岁,同理1939年7月6日,小明1周岁,1939年7月7日,小明2周岁。

Input
一个整数t(1<=t<=100),表示数据组数
对于每组测试数据,三个整数,逗号隔开,分别表示给定日期的年、月、日。给定的日期保证合法, 而且一定是小明出生后的日期,且小明的岁数保证在100以内。

Output
对于每一组数据,输出一个整数,表示小明的周岁数。

Sample Input
2
1938 7 6
1938 7 7

Sample Output
0
1

思路:

先年份相减,然后看月份和日期,若不够一年,则结果减一。真·签到题,没啥说的。

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int main(){    const int year=1937,month=7,day=7;    int T;    cin>>T;    while(T--)    {        int y,m,d;        cin>>y>>m>>d;        int ans=0;        ans=y-year;        if(m<month)            ans--;        if(m==month&&day>d)//如果不够一年的情况            ans--;        cout<<ans<<endl;    }    return 0;}
1 0