CF1872D 题解

洛谷传送门 & CF 传送门

思路

我们设 a=px+p2x+p3x++pnxxa=p_x+p_{2x}+p_{3x}+\ldots+p_{\lfloor\frac{n}{x}\rfloor\cdot x},设 alen=nxalen=\lfloor\frac{n}{x}\rfloor;设 b=py+p2y++pnyyb=p_{y}+p_{2y}+\ldots+p_{\lfloor\frac{n}{y}\rfloor\cdot y},设 blen=nyblen=\lfloor\frac{n}{y}\rfloor;设 ggaabb 中的公共部分,设 glen=nlcm(x,y)glen=\frac n{\operatorname{lcm}(x,y)}。去掉公共部分的 glenglen 个元素,alenalen 变成了 alenglenalen-glenblenblen 就变成了 blenglenblen-glen。我们要让 aba-b 最大,则要把 aa 设为最大的 n(nalen+1)n\sim(n-alen+1) 最小,bb 设为最小的 1(nblen)1\sim(n-blen)gg 部分随便设。根据等差数列求和公式,aa 的总和是 (n×2alen+1)×alen2\frac{(n\times2-alen+1)\times alen}2bb 的总和是 (blen+1)×blen2\frac{(blen+1)\times blen}2,答案就是 (n×2alen+1)×alen(blen+1)×blen2\frac{(n\times2-alen+1)\times alen-(blen+1)\times blen}2。记得开 long long。

代码

# include <bits/stdc++.h>
using namespace std;
typedef long long ll; //不开 long long 见祖宗
ll t, a, b, g, n;
int main () {
	cin >> t;
	while (t --) {
		cin >> n >> a >> b;
		g = a * b / __gcd (a, b); //lcm
		a = n / a, b = n / b, g = n / g; //算个数
		a -= g, b -= g; //减重复部分
		cout << ((n * 2 - a + 1) * a - (b + 1) * b) / 2 << '\n';
	}
	return 0;
}
posted @ 2023-09-19 13:54  Vitamin_B  阅读(10)  评论(0)    收藏  举报  来源