Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine))B. Charmed by the Game 题解

题目大意

A l i c e Alice Alice B o b Bob Bob打球,两个人轮流发球。每一轮以某一方胜利宣告结束。接球方胜利,则称为“打破发球”;发球方胜利,则称为“保持发球”。

已知 A l i c e Alice Alice赢了 a a a轮, B o b Bob Bob赢了 b b b轮,但不清楚谁先发球,也不清楚谁赢了哪轮游戏。让 k k k表示“打破发球”的次数,现在请你求出 k k k的所有可能取值。

输入描述

每次测试包含多组测试用例。

第一行一个 t ( 1 ≤ t ≤ 1 0 3 ) t(1≤t≤10^3) t(1t103)表示测试用例的数目,接下来t行每行一个测试用例包含 a a a b ( 0 ≤ a , b ≤ 1 0 5 ; a + b > 0 ) b(0≤a,b≤10^5;a+b>0) b(0a,b105;a+b>0)分别表示 A l i c e Alice Alice B o b Bob Bob获得胜利的游戏轮数。

保证所有测试用例的 a + b a+b a+b之和不超过 2 × 1 0 5 2×10^5 2×105

输出描述

对每组测试用例输出两行。

第一行一个 m ( 1 ≤ m ≤ a + b + 1 ) m(1≤m≤a+b+1) m(1ma+b+1)表示 k k k的所有可能取值有多少种。

第二行输出 m m m个不同的整数 k 1 , k 2 , … k m ( 0 ≤ k 1 < k 2 < … < k m ≤ a + b ) k_1,k_2,…k_m(0≤k_1<k_2<…<k_m≤a+b) k1,k2,km(0k1<k2<<kma+b),表示按照升序排列的所有 k k k的可能取值。

样例输入

3
2 1
1 1
0 5

样例输出

4
0 1 2 3
2
0 2
2
2 3

思路

假设 A l i c e Alice Alice先发球,一共进行了 a + b a+b a+b轮游戏。如果 a + b a+b a+b是偶数,那么两人都发了 a + b 2 \frac{a+b}{2} 2a+b轮球。如果 a + b a+b a+b是奇数,那么 A l i c e Alice Alice B o b Bob Bob多发一轮球。将两种情况整合成数学语言,那么 A l i c e Alice Alice发了 p = ⌈ a + b 2 ⌉ p=⌈\frac{a+b}{2}⌉ p=2a+b轮球, B o b Bob Bob发了 q = ⌊ a + b 2 ⌋ q=⌊\frac{a+b}{2}⌋ q=2a+b轮球。

假设 B o b Bob Bob“打破发球”的轮数是 x ( 0 ≤ x ≤ p ) x(0≤x≤p) x(0xp) A l i c e Alice Alice“打破发球”的轮数是 y ( 0 ≤ y ≤ q ) y(0≤y≤q) y(0yq),也就是说: B o b Bob Bob作为接球方赢了 x x x轮,作为发球方赢了 b − x b-x bx轮; A l i c e Alice Alice作为接球方赢了 y y y轮,作为发球方赢了 a − y a-y ay轮。因此, B o b Bob Bob作为接球方输了 a − y a-y ay轮, A l i c e Alice Alice作为接球方输了 b − x b-x bx轮。已知 B o b Bob Bob接了 p p p轮球, A l i c e Alice Alice接了 q q q轮球,对于固定的某一方,无论是接球还是发球只有输赢两种状态,我们得到方程: x + ( a − y ) = p x+(a-y)=p x+(ay)=p y + ( b − x ) = q y+(b-x)=q y+(bx)=q,变形得 x − y = p − a = b − q x-y=p-a=b-q xy=pa=bq。由于 p − a = b − q p-a=b-q pa=bq,我们任取 x − y = p − a x-y=p-a xy=pa,得约束方程 y = x + ( a − p ) ( 0 ≤ x ≤ p , 0 ≤ y ≤ q ) y=x+(a-p)(0≤x≤p,0≤y≤q) y=x+(ap)(0xp,0yq)。只需要求出所有满足约束方程的 ( x , y ) (x,y) (x,y),再代入 k = x + y k=x+y k=x+y即可。

当然,上面给出的是 A l i c e Alice Alice先发球的情况, A l i c e Alice Alice获胜的轮数为 a a a,发了 p p p轮球。对于 B o b Bob Bob先发球的情况, B o b Bob Bob仍发了 p p p轮球,获胜的轮数却为 b b b,因此我们只需交换 a , b a,b a,b的值,再重复一次上面的步骤即可。

考点

数学模型的建立
约束方程的推导

AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int T, a, b, p, q, k[maxn], vis[maxn], ans;
void init() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
}
int y(int x) {
	return x + a - p;
}
void pd() {
	for (int i = 0; i <= p; i++) {
		if (y(i) >= 0 && y(i) <= q) {
			if (vis[i + y(i)] == 0)ans++, k[ans] = i + y(i), vis[i + y(i)] = 1;
		}
	}
}
int main()
{
	init();
	while (T--) {
		cin >> a >> b;
		p = ceil((a + b)*1.0 / 2);
		q = (a + b) / 2;
		ans = 0;
		memset(vis, 0, sizeof(vis));
		pd();
		swap(a, b);
		pd();
		cout << ans << endl;
		sort(k + 1, k + 1 + ans);
		for (int i = 1; i <= ans; i++) {
			cout << k[i] << " ";
		}
		cout << endl;
	}
    return 0;
}

心得

t o u r i s t t\color{red}ourist tourist果然是世界第一啊,他出的这道 B B B题实在是让我痛心疾首,签出个 A A A后就罚了两小时坐。一开始我是尝试去找规律,以为是一道构造题,结果在纸上画了半天啥也推导不出来。比赛最后我干脆直接贪心过样例,没想到试的那种规律还真和最后的结论差不多 ( ( ( t o u r i s t t\color{red}ourist tourist的题解 ) ) )。赛后看题解才发现这道题用的是宏观的思想,类似建立数学模型,得到数学方程吧,最后和线性规划差不多,只是用计算机去求出所有的解。

这题不会超时,因为是所有测试用例中的 a + b a+b a+b之和不会超过 2 × 1 0 5 2×10^5 2×105,枚举是 O ( n ) O(n) O(n)的,排序是 O ( n l o g n ) O(nlogn) O(nlogn)的,只需要推导出中间结论。按照 t o u r i s t t\color{red}ourist tourist题解最后的结论,我还真差不多推导出来了,用了一下午。不过完全没必要,毕竟 t o u r i s t t\color{red}ourist tourist本人都没给出证明过程。考场上是绝对没有时间推导出最终结论的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

keguaiguai

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

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

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

打赏作者

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

抵扣说明:

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

余额充值