[2020-4-17]BNUZ套题比赛div3 题解

目录:

A - Greed 
B - Wrath 
C - Pride 
D - Splitting in Teams 
E - Months and Years 

A - Greed

solution

问能否用两个瓶子就装完这些水。先把水都加起来,然后找最大容量的两个瓶子比较即可。

AC_Code

#include<stdio.h>
long long int a[100001],b[100001];

int main()
{
	long long int n;
	long long int sum,max;
	while(~scanf("%lld",&n)) 
	{
		max = 0;
		long long int sum1=0,max1=0,l;
		for(int i=0; i<n; i++){
			scanf("%lld",&a[i]);
			sum1 += a[i];
		}
		for(int i=0; i<n; i++){
			scanf("%lld",&b[i]);
		}
		for(int i=0; i<n; i++){
			if(max < b[i]){
				max = b[i];
				l = i;
			}
		}
		for(int i=0; i<n; i++){
			if(max1 < b[i] && i!=l){
				max1 = b[i];
			}
		}
		
		sum = max + max1;
		if(sum < sum1){
			printf("NO\n");
		}
		else{
			printf("YES\n");
		}
	}	
	return 0;
 } 

B - Wrath

solution

每个人可借助长l的刀杀左边的人。最右边的人一定能活。从右向左看,当前人的后面所有人的刀都够不到时,则此人能活。

AC_Code

#include<stdio.h>
#include<iostream>
const int MAXSIZE = 2e6+10;
int l[MAXSIZE];

int main()
{
	int n;	
	int sum;
	while(~scanf("%d",&n))
	{
		for(int i=1; i<= n; i++){
			scanf("%d",&l[i]);
		} 
		int cnt = l[n];sum = 1; //最右边一个人总能活 
		for(int i=n-1; i>=1; i--){
			if( !cnt ){  //刀长不够 
				sum++;
			}
			if(l[i] > cnt-1){
				cnt = l[i];
			}
			else
				cnt = cnt-1;
		}
		printf("%d\n",sum);
	}	
	return 0;
}

C - Pride

solution

题意:你在给的数字里面选两个数,可以用这两数的最大公约数来替换其中一个,问最少几次可以他们都替换成1,如果无法做成,输出-1,否则输出替换次数。
因为只要有1,就可以把另一个任意数字换成1,1有m个,则次数为n-m;如果没有1,那我们需要求一个最小的把任意一个书换成1的次数m,然后用n-1+m

AC_Code

#include<stdio.h>
#include<iostream>
using namespace std;
int a[2009];

int gcd(int x,int y)
{
	int c ;
	while( x % y != 0){
		c = x % y;
		x = y;
		y = c;
	}
    return y;
}

int main()
{
    int n,sum;
    while(~scanf("%d",&n))
    {
        int a1=0;//记录1的个数
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==1) a1++;
        }
        if(a1)//有1
            printf("%d\n",n-a1);
        else//没1
        {
            int ans = 9999999;
            for(int i=0; i<n; i++)//遍历所有的情况,求最小步数。
            {
                int ans1 = 0, sum = a[i];
                for(int j=i+1; j<n; j++)
                {
                    ans1++;
                    sum = gcd(sum,a[j]);  //sum为最大公约数 
                    if(sum == 1)
                    {
                        ans = min(ans,ans1);
                        break;
                    }
                }
            }
            if(ans == 9999999)//如果没找到,输出-1
                printf("-1\n");
            else//找到1
                printf("%d\n",ans+n-1);
        }
    }
    return 0;
}

D - Splitting in Teams

solution

三个人组一个队,原队人数为2的组或不组都要一起。分别找原来有几队人数是2,几个1。若人数为2的队数大于人数为1的人数,人数为2的队都不能拆,只能分配人数为1的,则再组新队数为原队人数为1的。若人数为2的队数小于人数为1的人数,则先分配1,再看还剩几个1,再看有几个3个1。

AC_Code

#include<stdio.h>
const int MAXSIZE = 2e6+10;
int a[MAXSIZE];
int main()
{
	int n;
	while(~scanf("%d",&n)){
		for(int i=1; i<=n; i++){
			scanf("%d",&a[i]);
		}
		int sum = 0;
		int ans = 0,ans2 = 0;
		for(int i=1; i<=n; i++){
			if(a[i] == 2){
				ans++;
			}
			else{
				ans2++;
			}
		}
		if(ans > ans2){
			sum = ans2; 
		}
		else{
			sum = ans + (ans2-ans)/3;
		}
		printf("%d\n",sum);
	}
	return 0;
}

E - Months and Years

solution

由于 n≤24,这 n 个月包含在至多 3 年内,而三年的可能情况有:
闰年—平年—平年
平年—闰年—平年
平年—平年—闰年
平年—平年—平年

将这四种模式合并起来:
平年—平年—平年—闰年—平年—平年,然后暴力查找。

AC_Code

#include<stdio.h>
int a[72]= {31,29,31,30,31,30,31,31,30,31,30,31,
              31,29,31,30,31,30,31,31,30,31,30,31,
              31,29,31,30,31,30,31,31,30,31,30,31,
              31,28,31,30,31,30,31,31,30,31,30,31,
              31,29,31,30,31,30,31,31,30,31,30,31,
              31,29,31,30,31,30,31,31,30,31,30,31
             };//一一列举所有月份
int main()
{
	int n;
	int x[25];
	scanf("%d",&n);
	for(int i = 0; i < n; i++){
		scanf("%d",&x[i]);
	}
	for(int i = 0; i <= 72-n; i++)
    {
        if(x[0] == a[i])
        {
            bool ok = true;
            int t=0;
            for(int j=i; t<n; j++,t++)
            {
                if(x[t] != a[j]) 
					ok = false;
            }
            if(ok == true)
            {
                printf("YES\n");
                return 0; 
            }
        }
    }
	printf("NO\n"); 
	return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值