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

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 1234
using 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值