Codeforces - 1244C - The Football Season(暴力 + 数学规律 + 数论 / *2000)

1244C - The Football Season(⇔源地址








tag

⇔暴力、⇔数学规律、⇔数论、⇔*2000


题意

已知方程 \(\left\{\begin{matrix} x*w+y*d=p \\ x+y+z=n\end{matrix}\right.\) ,且满足 \(d<w\) ,求解一组正整数解 \(\{x,y,z\}\)


思路

暴力解(枚举)

第一个突破口很好看出来:由于一式与 \(z\) 无关,故 \(z\) 可以暂时不参与计算;只需要解出一组最小的 \(\{x,y\}\) ,再通过二式计算是否存在 \(z\) 即可。

第二个突破口在于变形一式,有:

\[x*w+w*d-w*d+y*d=p \]

\[\rightarrow (x+d)*w+(y-w)*d=p \]

我们发现,如果对于一组解 \(\{x_0,y_0\}\) 满足二式,那么一定有一组解 \(\{x_0-d,y_0-w\}\) 也满足二式,而后者的和小于前者,即后者更优

由此,我们发现,\(y\) 的取值是 \(0\le y < w\) ,暴力枚举 \(y\) 即得解。

一式的变形还有另外一种思路,如下:设 \(y \ge w\) ,那么记 \(y=\Delta + w\)

\[x*w+(\Delta+w)*d=p \]

\[\rightarrow (x+d)*w+\Delta * d=p \]


不过,需要注意的是,由此计算出来的值不一定是满足“正整数”这一条件的,如下例:

10 2 5 3

别忘记加上特判(否则会WA62)。


数论解(扩展欧几里得)

本题还能使用数论解,但是会爆 long long ,需要搭配 int128 食用,简单学习了下,过程如下。

由扩欧可得 \(x*w+y*d=\gcd(w,d)\) 的其中一组可行解,记为 \(\{x_0,y_0\}\) ;而当 \(p \mod \gcd(w,d)=0\) 时,可行解变为 \(\bigg\{x_0*\dfrac{p}{\gcd(w,d)},y_0*\dfrac{p}{\gcd(w,d)} \bigg\}\)

那么,该如何求解最小的一组 \(\{x,y\}\) 呢,我们还是回到上一种解法的变形上,即:用 \(d\)\(x\)\(w\)\(y\)更多思路与代码参考这里


AC代码

点击查看代码
bool Solve() {
	int n, p, w, d; cin >> n >> p >> w >> d;
	int y = 0;
	for (int y = 0; y < w; ++ y) {
		if ((p - y * d) % w) continue;
		int x = (p - y * d) / w, z = n - x - y;
		if (x >= 0 && z >= 0) {
			cout << x << " " << y << " " << z;
			return 0;
		}
	}
	cout << -1;
	return 0;
}

错误次数:2

忘写特判了……






文 / WIDA
2023.02.23 成文
首发于WIDA个人博客,仅供学习讨论

posted @ 2023-02-23 19:44  hh2048  阅读(36)  评论(0编辑  收藏  举报