思路
又又又是一道 CF 诈骗题。
对于 x x x 选出来的数,我们尽量放大的,对于 y y y 选出来的数,我们尽量放小的,但是呢,存在同时被 x x x 和 y y y 选出来的数,就随便放。
但是可以发现按照题目给的数据范围,这么找选择的数,然后放最大或者是放最小,肯定是超时。
所以我们可以直接算出有多少个 x x x 选出来的数和有多少个 y y y 选出来的数以及有多少个同时被 x x x 和 y y y 选出来的数就可以了。
很显然的, x x x 能选 ⌊ n x ⌋ \lfloor \frac n x \rfloor ⌊xn⌋ 个数, y y y 能选 ⌊ n y ⌋ \lfloor \frac n y \rfloor ⌊yn⌋ 个数,同时被 x x x 和 y y y 选的数有 ⌊ n gcd ( x , y ) ⌋ \lfloor \frac n {\gcd(x,y)}\rfloor ⌊gcd(x,y)n⌋ 个。
所以我们把只被 x x x 选的 ⌊ n x ⌋ − ⌊ n gcd ( x , y ) ⌋ \lfloor \frac n x \rfloor-\lfloor \frac n {\gcd(x,y)}\rfloor ⌊xn⌋−⌊gcd(x,y)n⌋ 个数都放成最大的,用等差数列求和就是 [ n + n − ( ⌊ n x ⌋ − ⌊ n gcd ( x , y ) ⌋ ) + 1 ] ∗ ( ⌊ n x ⌋ − ⌊ n gcd ( x , y ) ⌋ ) 2 \frac {[n+n-(\lfloor \frac n x \rfloor-\lfloor \frac n {\gcd(x,y)}\rfloor)+1]*(\lfloor \frac n x \rfloor-\lfloor \frac n {\gcd(x,y)}\rfloor)} 2 2[n+n−(⌊xn⌋−⌊gcd(x,y)n⌋)+1]∗(⌊xn⌋−⌊gcd(x,y)n⌋)。
再把只被 y y y 选的 ⌊ n y ⌋ − ⌊ n gcd ( x , y ) ⌋ \lfloor \frac n y \rfloor-\lfloor \frac n {\gcd(x,y)}\rfloor ⌊yn⌋−⌊gcd(x,y)n⌋ 个数都放成最小的,用等差数列求和就是 ( 1 + ⌊ n y ⌋ − ⌊ n gcd ( x , y ) ⌋ ) ∗ ( ⌊ n y ⌋ − ⌊ n gcd ( x , y ) ⌋ ) 2 \frac {(1+\lfloor \frac n y \rfloor-\lfloor \frac n {\gcd(x,y)}\rfloor)*(\lfloor \frac n y \rfloor-\lfloor \frac n {\gcd(x,y)}\rfloor)} 2 2(1+⌊yn⌋−⌊gcd(x,y)n⌋)∗(⌊yn⌋−⌊gcd(x,y)n⌋)。
式子看着复杂,实际上很简单,自己想一想就能明白。
AC code
#include<bits/stdc++.h>
using namespace std;
long long T,n,a,b,lc,dn,xn;
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld",&n,&a,&b),lc=a*b/__gcd(a,b),dn=n/a-n/lc,xn=n/b-n/lc;
printf("%lld\n",(n+n-dn+1)*dn/2-(1+xn)*xn/2);
}
}