USACO 2021 January Contest, Bronze

文章讲述了两个编程问题。第一个问题是关于奶牛唱字母歌的,给定一个特定的字母序列,需要计算唱完整首歌的最少次数。第二个问题涉及到将奶牛按奇偶编号分组,使得编号和的奇偶性交替。第三个问题讨论如何安排不同高度的奶牛进入有限制的牛棚,求解满足条件的安排方式数量。每个问题都提供了解题思路和示例代码。
摘要由CSDN通过智能技术生成

Problem 1. Uddered but not Herd

一个鲜为人知的事实是,奶牛拥有自己的文字:「牛文」。牛文由 26 个字母 ‘a’ 到 ‘z’ 组成,但是当奶牛说牛文时,可能与我们所熟悉的 ‘abcdefghijklmnopqrstuvwxyz’ 不同,她会按某种特定的顺序排列字母。
为了打发时间,奶牛 Bessie 在反复哼唱牛文字母歌,而 Farmer John 好奇她唱了多少遍。

给定一个小写字母组成的字符串,为 Farmer John 听到 Bessie 唱的字母,计算 Bessie 至少唱了几遍完整的牛文字母歌,使得 Farmer John 能够听到给定的字符串。Farmer John 并不始终注意 Bessie 所唱的内容,所以他可能会漏听 Bessie 唱过的一些字母。给定的字符串仅包含他记得他所听到的字母。

输入格式(从终端/标准输入读入):

输入的第一行包含 26 个小写字母 ‘a’ 到 ‘z’ 的牛文字母表顺序。下一行包含一个小写字母组成的字符串,为 Farmer John 听到 Bessie 唱的字母。字符串的长度不小于 1 且不大于 1000。

输出格式(输出至终端/标准输出):

输出 Bessie 所唱的完整的牛文字母歌的最小次数。

输入样例:

abcdefghijklmnopqrstuvwxyz
mood

输出样例:

3

在这个样例中,牛文字母表与日常的字母表的排列一致。

Bessie 至少唱了三遍牛文字母歌。有可能 Bessie 只唱了三遍牛文字母歌,而 Farmer John 听到了以下被标记为大写的字母。

abcdefghijklMnOpqrstuvwxyz
abcdefghijklmnOpqrstuvwxyz
abcDefghijklmnopqrstuvwxyz

测试点性质:

测试点 2-5 中,牛文字母表与日常的字母表相同。
测试点 6-10 没有额外限制。
供题:Nick Wu

其实这一题虽然看起来不好代码实现,但是其实很简单,我由于没有赋值,这题卡了一个半小时(悲),要说我后面两题加起来的时间都没这多QWQ

解题思路

我们弄一个标记为p用来查看当前查找的字母所在位置是否比之前的靠后,若靠后,证明在同一首歌里,否则是换成另一首歌

方法

硬核模拟+STL

代码展示

#include <bits/stdc++.h>
using namespace std;

string a;
char b;

int main(){
	freopen("herd.in","r",stdin);
	freopen("herd.out","w",stdout);
	int ans=1;
	cin>>a;
	int p=-1;
	while(cin>>b){
		int k=a.find(b);
		if(k>p){
			p=k;
			continue;
		}
		else{
			ans++;
			p=k;
		}
	}
	cout<<ans<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}

Problem 2. Even More Odd Photos

Farmer John 正再一次尝试给他的 N 头奶牛拍照(2≤N≤1000)。
每头奶牛有一个范围在 1…100 之内的整数的「品种编号」。Farmer John 对他的照片有一个十分古怪的构思:他希望将所有的奶牛分为不相交的若干组(换句话说,将每头奶牛分到恰好一组中)并将这些组排成一行,使得第一组的奶牛的品种编号之和为偶数,第二组的编号之和为奇数,以此类推,奇偶交替。

Farmer John 可以分成的最大组数是多少?

输入格式(从终端/标准输入读入):

输入的第一行包含 N。下一行包含 N 个空格分隔的整数,为 N 头奶牛的品种编号。

输出格式(输出至终端/标准输出):

输出 Farmer John 的照片中的最大组数。可以证明,至少存在一种符合要求的分组方案。

输入样例:

7
1 3 5 7 9 11 13

输出样例:

3

在这个样例中,以下是一种分成最大组数三组的方案。将 1 和 3 分在第一组,5、7 和 9 分在第二组,11 和 13 分在第三组。

输入样例:

7
11 2 17 13 1 15 3

输出样例:

5

在这个样例中,以下是一种分成最大组数五组的方案。将 2 分在第一组,11 分在第二组,13 和 1 分在第三组,15 分在第四组,17 和 3 分在第五组。

供题:Nick Wu

解题思路

这一题主要如果想让这个队列是偶,奇,偶,奇 … \ldots 那么我们只有两种可能:
可能一:偶数与奇数个数相等
可能二:偶数比奇数个数多1
当然,第二种可能长度更长一些
但是我们知道,如果给你足够多的奇数和偶数,我们可以通过奇数创造偶数,却不能通过偶数创造奇数,所以我们可以以奇数为突破口,创造出来我们理想的"可能二",然后如果创造完以后仍然发现偶数比奇数多的个数不止一个,我们就不需要管多出来的偶数,因为多出来的偶数可以合并到之前的偶数中,但他仍然是偶数,不影响队列,所以保证偶数比奇数多1就行,最后输出奇偶之和,就解决了

方法

数学证明

代码展示

#include <bits/stdc++.h>
using namespace std;

int n,a,j,o;

int main(){
	freopen("group.in","r",stdin);
	freopen("group.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a;
		if(a%2==0) o++;
		else j++;
	}
	while(j>o){
		j-=2;
		o++;
	}
	if(o-j>1)
		o=j+1;
	cout<<o+j<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}

Problem 3. Just Stalling

Farmer John 有 N 头奶牛(1≤N≤20),高度为 a 1 … a N a_1…a_N a1aN。他的牛栏有 N 个牛棚,高度限制分别为 b 1 … b N b_1…b_N b1bN(例如,如果 b 5 = 17 b_5=17 b5=17,那么一头高度不超过 17 的奶牛可以住在牛棚 5 里)。Farmer John 有多少种不同的方式安排他的奶牛,使得每头奶牛均住在不同的牛棚里,并且使得每个牛棚的高度限制均得到满足?

输入格式(从终端/标准输入读入):

输入的第一行包含 N。第二行包含 N 个空格分隔的整数 a 1 , a 2 , … , a N a_1,a_2,…,a_N a1,a2,,aN。第三行包含 N 个空格分隔的整数 b 1 , b 2 , … , b N b_1,b_2,…,b_N b1,b2,,bN。所有的高度和高度限制均在范围 [1,109] 内。

输出格式(输出至终端/标准输出):

输出 Farmer John 可以将每头奶牛安排到不同的牛棚里,使得每个牛棚的高度限制均得到满足的方法数。注意输出的数量可能需要使用 64 位整数型,例如 C++ 中的 long long。

输入样例:

4
1 2 3 4
2 4 3 4

输出样例:

8

在这个例子中,我们不能将第三头奶牛安排到第一个牛棚里,因为 3 = a 3 > b 1 = 2 3=a_3>b_1=2 3=a3>b1=2。类似地,我们不能将第四头奶牛安排到第一或第三个牛棚里。一种符合高度限制的安排方式为将奶牛 1 安排到牛棚 1,奶牛 2 安排到牛棚 2,奶牛 3 安排到牛棚 3,奶牛 4 安排到牛棚 4。

测试点性质:

测试点 1-5 满足 N≤8。
测试点 6-12 没有额外限制。
供题:Shreyas Thumathy

解题思路

我们首先将奶牛的身高和牛棚的高度排个序,然后从大到小枚举奶牛可以通过的牛棚数量,由于身高更高的奶牛可以通过,所以在他前面的奶牛就也可以通过那个牛棚,所以通过排列组合公式直接算出来输出答案。

方法

long long+sort+排列组合

代码展示

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int MAXN=50;

int n,h[MAXN],st[MAXN];

int main(){
	freopen("stalling.in","r",stdin);
	freopen("stalling.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>h[i];
	for(int i=1;i<=n;i++)
		cin>>st[i];
	sort(h+1,h+n+1);
	sort(st+1,st+n+1);
	ll m,rl=1;
	for(int i=n;i>=1;i--){
		m=0;
		for(int j=n;j>=1;j--){
			if(h[i]<=st[j]){
				m++;
			}
		}
//		cout<<m<<" "<<n-i<<endl;
		rl*=m-(n-i);
	}
	cout<<rl<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值