2021-01-29

2021 UPC 第十五场


前言

这场模拟思维题多,其实也是因为其他的题看一眼就知道不会,而且那个a题数据到底是什么,上来就被卡,还好重写一遍过了。


C 采药(01背包)

辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带 到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时 间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
模板题,不多赘述了


#include <bits/stdc++.h>
//#define maxn 20001
using namespace std;
int dp[101][1001];
int w[101],v[101];
int main()
 {
 	int n,m,k;
 	cin >> m >> n;
 	for(int i=1;i<=n;i++)
    {
        cin >> w[i] >> v[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=0;j--)
        {
            if(j>=w[i])
            {
                dp[i][j]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j]); //状态转移方程
            }
             else{
                dp[i][j]=dp[i-1][j];
             }
        }
    }
    cout << dp[n][m];
 	return 0;
 }

E AtCodeer 和油漆罐(stl集合)

最近买了三个油漆罐。他两天前买的那个是 a ,昨天买的颜色是 b ,他今天买的颜色是 c 。在这里,每个油漆的颜色可以由介于 1 和 100 之间的整数表示,包括。
由于他健忘,他可能买了不止一个相同颜色的油漆罐。数数这些油漆罐中不同颜色的数量,然后告诉他。

约束 1≤a,b,c≤100

题意:就是让你维护一个最大元素数是3的集合,输出元素数

#include <bits/stdc++.h>
//#define maxn 20001
using namespace std;
int ans,tao,x;
int a[11];
int main()
{
    set<int>s;
	for(int i=0;i<3;i++)
    {
		scanf("%d",&x);
		s.insert(x);
	}
	printf("%d\n",s.size());
	return 0;
}

F AtCodeer 画球(快速幂,组合数学)

一排放置了 N 个球。在鹿的油漆罐的K色中,鹿正在画每一种颜色。出于审美原因,任何两个相邻的球必须涂成不同的颜色。
找到画球的可能方法的数量。

约束 1≤N≤1000 2≤K≤1000

正确答案最多为 2的31次方+1.
题意:可以推出一个公式k*pow(n-1,k-1),次数较大,故考虑使用快速幂来维护防超时(也可能不会超)

#include <bits/stdc++.h>
//#define maxn 20001
using namespace std;
long long ksm(long long  k,long long  n)  //快速幂模板
{
	long long  ans=1;
	while(n)
    {
		if(n&1) ans=ans*k;
		k=k*k;
		n>>=1;
	}
	return ans;
}
int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	printf("%lld\n",k*ksm(k-1,n-1));
	return 0;
}

G AtCodeer 和选举报告(思维)

鹿在电视上看到一份快速的选举结果报告。两位候选人正在竞选:高桥和青木。报告显示两位候选人目前获得的选票数的比率,但不包括实际得票数。AtCoDeer 检查了报告 N 次,当他检查报告时,i-th (1≤i≤N) 的比率为 Ti:Ai。众所周知,每位候选人在第一次检查报告时至少获得一票。
查找两位候选人在 N-1 次检查报告时获得的最小可能的总票数。可以假定,每个候选人获得的选票数永远不会减少。
约束 1≤N≤1000 1≤Ti,Ai≤1000(1≤i≤N) Ti 和 Ai (1≤i≤N) 是共性。
保证正确答案最多为 10的18次方.
思路:其实别被题目吓到,你拿笔算一算模拟一下,具体看代码


#include <bits/stdc++.h>
//#define maxn 20001
using namespace std;
//int a[10001],q,z;
int main()
{
    long long int x,y,n,m,a,b;
    cin >> n >> x >> y;
    for(int i=2;i<=n;i++)
    {
        long long int c=0,d=0;  //先定义好上面两个变量的最小倍增数
        cin >> a >> b;
        if(a>=x&&b>=y)   //输入的a,b满足这个条件时,说明没有化简,就是我们要的原始数据,更新即可
        {
		 	x=a,y=b;
		 	continue;
        }
         if(a<x)
         {
		 	c=(x+a-1)/a;
		 }
		 if(b<y)
		 {
		 	d=(y+b-1)/b;
		 }
		 long long maxn=max(c,d);  //跟着大的倍整数走,注意数据范围
		 x=a*maxn,y=b*maxn;        
    }
   printf("%lld\n",x+y);  
	return 0;
}

H AtCoDeer and Rock-Paper(贪心)

tCoDeer the deer and his friend TopCoDeer is playing a game. The game consists of N turns. In each turn, each player plays one of the two gestures, Rock and Paper, as in Rock-paper-scissors, under the following condition:
(※) After each turn, (the number of times the player has played Paper)≤(the number of times the player has played Rock).
Each player’s score is calculated by (the number of turns where the player wins) − (the number of turns where the player loses), where the outcome of each turn is determined by the rules of Rock-paper-scissors.
(For those who are not familiar with Rock-paper-scissors: If one player plays Rock and the other plays Paper, the latter player will win and the former player will lose. If both players play the same gesture, the round is a tie and neither player will win nor lose.)
With his supernatural power, AtCoDeer was able to foresee the gesture that TopCoDeer will play in each of the N turns, before the game starts. Plan AtCoDeer’s gesture in each turn to maximize AtCoDeer’s score.
The gesture that TopCoDeer will play in each turn is given by a string s. If the i-th (1≤i≤N) character in s is g, TopCoDeer will play Rock in the i-th turn. Similarly, if the i-th (1≤i≤N) character of s in p, TopCoDeer will play Paper in the i-th turn.

Constraints
1≤N≤105
N=|s|
Each character in s is g or p.
The gestures represented by s satisfy the condition (※).
思路:贪心,但是注意题目给的限制,能出布尽量出;

#include <bits/stdc++.h>
//#define maxn 20001
using namespace std;
//int a[10001],q,z;
int main()
{
    string a;
    cin >> a;
    int sum=0;
    int p=0;
    for(int i=0;i<a.size();i++)
    {
        if(a[i]=='g')
        {
            if(p>0)
            {
                sum++;
                p--;
            }
            else
            {
                p++;
            }
        }
        else
        {
            if(p>0)
            {
                 p--;
            }
            else
            {
                 p++;
                sum--;
            }

        }
    }
    cout << sum << endl;
    return 0;
}

K 社交距离 1(模拟,暴力)

一种可怕的新疾病,COWVID-19,已经开始在全世界的奶牛中传播。农夫约翰正设法采取尽可能多的预防措施,以保护他的家免受感染。
农民约翰的谷仓是一个长狭窄的建筑,有N个摊位在一排(2≤N≤105).其中一些摊位目前被奶牛占据,有些是空置的。在阅读了"社会疏远"的重要性后,农民约翰想要最大化D,其中D是最接近的两个被占领的摊位之间的距离。例如,如果停滞点 3 和 8 是最近占用的,则 D=5。

最近有两头新奶牛加入了农夫约翰的牛群,他需要决定他们应该分配哪些以前无人居住的摊位。请确定他如何放置他的两头新奶牛,以便D的生成值仍然尽可能大。农夫约翰不能移动他现有的任何奶牛;他只想给新奶牛分配摊位。
思路:1.二分(不会写)
2.分类讨论,有四种
(1)都放在首或者尾;
(2)都放在最大的空里
(3)都放在最大的空和次大的空里
(4)一个放在头或尾,一个放在最大的空里
这就是94分的做法,要想得100,还得特判没有牛的情况,具体看代码

#include <bits/stdc++.h>
using namespace std;
int n,m,maxn1,maxn2,x,y,df=90000000;
int a[100009],ls,kl,ji,jk;
char c;
int main()
{
	cin >> n;
	for(int i=1; i<=n; i++)
	{
		cin >> c;
		if(c=='1')
		{
			m++,a[m]=i;
			if(m>1) //非队首
		 	{
				df=min(df,a[m]-a[m-1]);
				if(a[m]-a[m-1]>=maxn1)
				{
					maxn2=maxn1;
					maxn1=a[m]-a[m-1];
				}
				else
				{
					maxn2=max(maxn2,a[m]-a[m-1]);
				}
			}
		}
	}
	x=min(maxn1/2,maxn2/2); //放中间两个区间里
	y=maxn1/3; //放在中间一个区间
	if(a[1]>1)
	{
	    kl=min(a[1]-1,maxn1/2);//一个头一个最大区间
		x=max(x,kl);
		y=max(y,(a[1]-1)/2);  //两个放在首
	}
	if(a[m]<n)
	{
	    ji=min(n-a[m],maxn1/2);//一个尾一个最大区间
         x=max(x,ji);
		y=max(y,(n-a[m])/2);  //两个都放在尾
	}
	if(a[1]>1&&a[m]<n)
	{
		ls=min(a[1]-1,n-a[m]); //放首尾
	}
	jk=max(x,max(y,ls));
	if(m==0)
    {
        cout << n-1;
    }
    else
    {
         cout << min(df,jk);
    }
	return 0;
}



L 社交距离 2(思维)

尽管他尽了最大的努力,让他的N牛(1≤N≤1000)练习"社会疏远",他们中的许多人仍然不幸地感染了这种疾病。奶牛,方便编号1…N, 每个站在沿着一条长路径的不同点 (基本上是一维数线), 牛 i 站在位置 xi 。农民 John 知道有一个半径 R,这样任何站在 R 单位, 包括 R‎‎单位远离受感染的牛也会被感染 (然后将感染传递给其他奶牛在 R 单位远离, 等等).‎
‎不幸的是, 农民约翰并不完全了解 R ‎‎。然而,他知道他的哪头牛被感染了。鉴于这些数据,请确定最初感染该病的奶牛的最低数量。‎
思路:我们可以先写找到满足现有情况最小传播半径,说白了就是现有未患病到患病得最小距离,之后统计数目即可,此外,我感觉并查集也能做这个题

#include <bits/stdc++.h>
using namespace std;
long long n,a[1000001],x,y,minn=91010101,maxn,sum;
int main()
{
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		cin >> x >> y;
		maxn=max(maxn,x);
		if(!y)
        {
            a[x]=1;
        }
		else
        {
            a[x]=2;
        }
	}
	x=1100000,y=2200000;//别忘了开始可没有x,y
	for(int i=1;i<=maxn;i++)
	{
		minn=min(minn,abs(x-y)-1);
		if(a[i]==1)
        {
            y=i;
        }
		if(a[i]==2)
		{
		    x=i;
		}
	}
	minn=min(minn,abs(x-y)-1);
	x=-1;
	for(int i=1;i<=maxn;i++)
    {
        if(a[i]==2)   
		{
			if(i>x) sum++;
			x=i+minn;  //注意这个别忘了可以连续传播,而我们要统计的是初代患者
		}
    }
	printf("%d\n",sum);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

\ 安 /

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值