Codeforces刷题记录(tag: combinatorics 873 ~ 1073)

单词记录:

1.calculate v.计算 subsequence n.子序列 equal v.等于 obtained from 来自于 a single 一个 guaranteed v.保证
the elements of the array 数组中的元素 The first line contains a single integer t 第一行包含一个正整数t
exceed v.超过 construct v.构造 
2.highway n.公路 Traffic cars n.交通汽车 hindrances n.阻碍  races n.比赛   track n.轨道
divided adj.分裂的  represents v.代表 the number of ....的数量   the inconvenience 不便之处(代价,花费)
where |x| is the absolute value of x. 其中|x|是x的绝对值。
You can perform the following operation any (possibly zero) number of times: 你可以执行以下任何(可能是零)次的操作:
the minimum inconvenience. 最小的花费(代价)
3.The principal wishes.... 校长希望....  split v.拆分,分裂 distinct adj.不同的 letter n.字母,信
Two distinct students whose name starts with the same letter will be chatty. 名字以相同字母开头的两个不同的学生会很健谈
4.Latin 拉丁文  lowercase Latin letters 小写拉丁字母 How many different strings can you obtain?  你可以得到多少个不同的字符串
In one move 在一次操作中  any 任何 arbitrary adj.任意的 
Note that after the replacement.  请注意,在替换之后  Print the number, or report that it is infinitely large.  打印这个数字,或者报告它是无限大的。
Two strings are considered different if they have different length, or they differ at some index.
如果两个字符串的长度不同,或者它们在某些索引上不同,则被认为是不同的。
5. participating v.参与 participant n.参与者 x minutes intervals x分钟的间隔。Duration of contest is t minutes for each participant,每个参赛者的比赛时间为t分钟。
dissatisfaction n. 不满意
6. opponents a common question   反对者一个共同的问题  opponent n.反对者
All participants failing to answer are eliminated. 所有未能回答的参与者将被淘汰。
The show ends when only JOE remains (we assume that JOE never answers a question wrong!) 
当只剩下JOE的时候,节目就结束了(我们假设JOE从来不会回答错问题!)。
 the optimal scenario 最佳方案 consequently 结果 left for the next question 留给下一个问题  receive v.收到
 7. positive integer 正整数 obviously adv.显然地 Pasha likes rectangles but hates squares 帕沙喜欢长方形,但讨厌正方形
 how many ways are there to split a stick into four parts so that it's possible to form a rectangle using these parts, but is impossible to form a square.
 有多少种方法可以将一根棍子分成四部分,从而有可能用这些部分组成一个长方形,但不可能组成一个正方形。
1.题目名称:B. Luntik and Subsequences 1582B
2.思路:

题目要求的是一个长度为n总和为s的序列,其子序列总和为s - 1的序列的个数。我们可以发现,任意一个合法的子序列等价于一个删去一个值为1的元素且包含0个或若干个0的子序列。
令0的个数为cnt0,1的个数为cnt1。
故答案为 2 c n t 0 ∗ c n t 1 2^{cnt0} * cnt1 2cnt0cnt1

3.代码:
#include <iostream>
 
using namespace std;
 
int main()
{
	int t;
	cin >> t;
	while(t --)
	{
		int n;
		cin >> n;
		int cnt0 = 0, cnt1 = 0;
		for(int i = 0; i < n; i ++)
		{
			int x;
			cin >> x;
			if(x == 0) cnt0 ++;
			else if(x == 1) cnt1 ++;
		}
		cout << (1ll << cnt0) * (long long)cnt1 << endl;
	}
	return 0;
}
4.总结:
  • 当求一个问题的方案数的时,可以从另外一个角度来看待问题,将问题进行转化,比如此题:要求总和为s-1的子序列的个数,直接求不好求,所以我们换个角度看待这个问题,满足要求的子序列会删去一个1和若干个0(当然也可以一个0都不删),因此问题转化为求恰好删去一个1且包含0个或若干个0的子序列。故答案为 2 c n t 0 ∗ c n t 1 2^{cnt0} * cnt1 2cnt0cnt1

1.题目名称: B. Customising the Track 1543B
2.思路:

我们可以发现轨道的代价就是 所有子道上面的车辆数的 所有(a[i],a[j])对数之间的差值的绝对值的总和。
显而易见,每一个a[i]越平均则花费越小。因此,我们可以通过题目所给操作,求平均数。
若sum 是 n 的倍数,说明每一条车道上面的数都相同,故代价为0;
若sum 不是 n 的倍数,说明一共有 sum % n 条车道上面会多一辆交通车,故代价为(sum % n) * (n - sum % k)。

3.代码:
#include <bits/stdc++.h>

using namespace std;

int t;
int main()
{
	cin >> t;
	while(t --)
	{
		int n;
		cin >> n;
		long long sum = 0;
		for(int i = 0; i < n; i ++)
		{
			int x;
			cin >> x;
			sum += x;
		}
		long long s = sum % n;//一共有s条车道 会比平均值多1。 
		long long ans = s * (n - s);//一共的组合数  s * (n - s); 
		cout << ans << endl;
	}	
	return 0;
}
4.总结:
  • 给定n个数,要让任意数对的差的绝对值的总和最小,则将其求平均数便可得到最小。

1.题目名称:A. Silent Classroom 1166A
2.思路:

只有一组测试数据,最多有100个人,我们根据名字首字母分类统计,以每个字母开头的有几个人。
现在要求的就是 如何将相同字母的人,分配到两个教室,然后爱说话的对数最少,枚举一下所有字母,把答案累加起来即可。
当n = 100时。
我们可以发现 均分在两个教室的答案就是 C 50 2 ∗ 2 C^2_{50} * 2 C5022。如果一个教室98,一个教室两个人答案就是 C 2 2 ∗ C 98 2 C^2_2 * C^ 2 _{98} C22C982
前者是远小于后者的。
所以对于每一个字母,我们将其均分再计算。

3.代码:
#include <bits/stdc++.h>

using namespace std;

const int N = 61;
map<char, int> cnt;
int C[N][N];
void init()
{
	for(int i = 0; i < N; i ++)
		for(int j = 0; j <= i; j ++)
		if(!j) C[i][j] = 1;
		else C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
int main()
{
	init();
	int n;
	cin >> n;
	for(int i = 0; i < n; i ++)
	{
		string a;
		cin >> a;
		cnt[a[0]] ++;
 
	}
	int sum = 0;
	//cout << C[1][2] << endl;
	for(char i = 'a'; i <= 'z'; i ++)
	{
	
		int s = cnt[i];
		if(s == 0) continue;
		
		if(s & 1)
		{	 
			sum +=  C[s / 2][2] + C[s / 2 + 1][2];
			//cout << C[s / 2][2] << " " << C[s / 2 + 1][2] << endl;
		}
		else
		{
			sum += C[s / 2][2] * 2;
		}
	}
	cout << sum << endl;
	return 0;
}
4.总结:

求组合数时,
C b a 当 a 固定时, b 取中间值 b / 2 时值最小。当 b 固定时, a 取中间值 a / 2 时值最大 C^a_b当a固定时,b取中间值 b/2时值最小。当b固定时,a取中间值 a/2时 值最大 Cbaa固定时,b取中间值b/2时值最小。当b固定时,a取中间值a/2时值最大


1.题目名称:C.Infinite Replacement 1674C
2.思路:

题目的意思就是,给定一个只有a的字符串s,再给定一个字符串t。然后用t去替换s中的a,求一共有多少种不同的方案。
我们考虑s串的长度,每一次替换之后会造成什么影响(替换后a的数量是不变,还是增多,还是减少)。
1.当t的长度为1,且是字母a时。不管怎么样替换答案只有一种。
2.当t的长度为1,且不是字母a时。因为每一次替换,原串s的a都会减少一个,所以这种情况有解,每个a都有替换和不替换两种情况,故答案为 2 s . s i z e ( ) 2^{s.size()} 2s.size()
3.当t的长度大于1时,若a的数量大于等于1,则每一次替换,原串s的a的数量都不会变少,所以此情况有无数种方案。
4.当t的长度大于1时,若a的数量为0,则每一次替换,原串s的数量都会减一,所以此情况有 2 s . s i z e ( ) 2^{s.size()} 2s.size()

3.代码:
#include <bits/stdc++.h>

using namespace std;

int t;
int main()
{
	cin >> t;
	while(t --)
	{
		string s, t;
		cin >> s >> t;
		int sizet = t.size();
		//记录a里面的数量 
		int cnta = 0;
		for(int i = 0; i < sizet; i ++) if(t[i] == 'a') cnta++;
		//分类讨论 
		if(sizet == 1 && t[0] == 'a') cout << 1 << endl;
		else if(sizet == 1 && t[0] != 'a') cout <<(1ll << s.size())<< endl;
		else if(sizet > 1 && cnta >= 1) cout << -1 << endl;
		else if(sizet > 1 && cnta == 0) cout << (1ll << s.size()) << endl;
	}
	return 0;
}
4.总结:
  • 多思考,某个操作之后,和操作之前状态的进行对比,然后分类讨论。

1.题目链接:A. Contest Start 1539A
2.思路:

第i个人,参加比赛的时间是(i - 1) + i * x,比赛完的时间是,(i - 1) + i * x + t。我们可以根据此得到每个人在比赛时间段,
当t / x的时候,也就是说,当前这个人比赛比完了,下一个还没开始。所以这种情况答案为0。
当有交集的时候,每一次影响当前完赛的这个人的人数应该为 t / x。
当t / x小于n的时候,可以发现具有一定规律。
在这里插入图片描述
当t/x大于等于n - 1时,呈现一定规律。
在这里插入图片描述

3.代码:
#include <bits/stdc++.h>

using namespace std;
int k;
int main()
{
	cin >> k;
	while(k --)
	{
		long long n, x, t;
		cin >> n >> x >> t;
		long long s1 = 0;
		long long m = t / x;
		if(t < x)
		{	
			puts("0");
			continue;
		}
		else if(t / x >= n - 1) s1 = n * (n - 1) / 2;
		else 
		{
			s1 = m * (n - m) +  m * (m - 1) / 2;
		}
		cout << s1<< endl;
	}
	return 0;
}
4.总结:
  • 对于规律性的题目,可以通过画图来解决。

#### 1.题目名称:B. JOE is on TV! 1293B

2.思路:

直接暴力循环O(n)即可。

3.代码:
#include <bits/stdc++.h>

using namespace std;

int main()
{
	long long n;
	cin >> n;
	double ans = 0;
	for(int i = n; i >= 1; i --) ans += 1.0 / i;
	printf("%.12lf\n", ans);
	return 0;
}


4.总结:
  • 结论: i n < 1 n + 1 n − 1 + 1 n − 2 + . . . . . + 1 n − i 结论:\frac{i}{n} < \frac{1}{n} + \frac{1}{n - 1} +\frac{1}{n - 2} + ..... + \frac{1}{n - i} 结论:ni<n1+n11+n21+.....+ni1

1.题目链接:A. Pasha and Stick 610A
2.思路:

给定一个长度为n的木棍,切割三次分为四段。
求这四段可以围成一个长方形的方案数。
4段能拼成一个正方形当且仅当n是4的倍数,且方案数只有1。
求(a,a,b,b)组成n的方案数的等价于求(a,b)等于 n / 2的方案数。
等价于 1 <= a,b <= n / 2中有多少个数对(a,b)加起来等于n / 2。
拼成长方形为(n / 2) / 2。
故答案为(n / 2) / 2。若n是4的倍数则需要-1。

3.代码:
#include <bits/stdc++.h>

using namespace std;

long long C(long long a, long long b)
{
	return a * (a - 1) / 2;
}
int main()
{
	int n;
	cin >> n;
	long long ans = 0;
	if(n <= 4 || (n & 1)) ans = 0;//如果小于等于4,或者 是奇数则无解 
	else if(n % 4 == 0) ans = n / 2 / 2 - 1;//对于一个长度为n的线段,分割成四段相等的子段当且仅当是4的倍数。且只有一种分法。 
	else ans = n / 2 / 2;
	cout << ans << endl;
	return 0;
}
4.总结:
  • 一个长度为n的线段分成4段,这4段能拼成一个正方形当且仅当n是4的倍数,且方案数只有1。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值