题目
CF
注意最后一个周期可以不是满的,其实说最小有点不严谨
1
≤
a
,
b
≤
1
0
9
1\le a,b\le 10^9
1≤a,b≤109
思路
首先我们思考一个比较暴力的做法,枚举周期
k
k
k ,我们记
a
+
b
=
n
a+b=n
a+b=n
我们假设一个周期内
A
A
A 的数量为
x
x
x ,
B
B
B 的数量为
y
y
y,我们可以得到:
{
0
≤
a
−
⌊
n
k
⌋
∗
x
≤
x
0
≤
b
−
⌊
n
k
⌋
∗
y
≤
y
\begin{cases} 0\le a-\lfloor \frac{n}{k}\rfloor*x\le x\\ 0\le b-\lfloor \frac{n}{k}\rfloor*y\le y \end{cases}
{0≤a−⌊kn⌋∗x≤x0≤b−⌊kn⌋∗y≤y
我们可以得到
{
a
⌊
n
k
⌋
+
1
≤
x
≤
a
⌊
n
k
⌋
b
⌊
n
k
⌋
+
1
≤
y
≤
b
⌊
n
k
⌋
\begin{cases} \frac{a}{\lfloor \frac{n}{k}\rfloor+1}\le x\le \frac{a}{\lfloor \frac{n}{k}\rfloor}\\ \frac{b}{\lfloor \frac{n}{k}\rfloor+1}\le y\le \frac{b}{\lfloor \frac{n}{k}\rfloor} \end{cases}
{⌊kn⌋+1a≤x≤⌊kn⌋a⌊kn⌋+1b≤y≤⌊kn⌋b
因为
x
,
y
x,y
x,y 均为整数,我们又可以写为:
{
⌈
a
⌊
n
k
⌋
+
1
⌉
≤
x
≤
⌊
a
⌊
n
k
⌋
⌋
⌈
b
⌊
n
k
⌋
+
1
⌉
≤
y
≤
⌊
b
⌊
n
k
⌋
⌋
\begin{cases} \lceil\frac{a}{\lfloor \frac{n}{k}\rfloor+1}\rceil\le x\le \lfloor\frac{a}{\lfloor \frac{n}{k}\rfloor}\rfloor\\ \lceil\frac{b}{\lfloor \frac{n}{k}\rfloor+1}\rceil\le y\le \lfloor\frac{b}{\lfloor \frac{n}{k}\rfloor}\rfloor \end{cases}
{⌈⌊kn⌋+1a⌉≤x≤⌊⌊kn⌋a⌋⌈⌊kn⌋+1b⌉≤y≤⌊⌊kn⌋b⌋
看到这个我们就想到了数论分块,因为
⌊
n
k
⌋
\lfloor \frac{n}{k}\rfloor
⌊kn⌋ 最多只有
2
n
2\sqrt n
2n 个取值,枚举
t
=
⌊
n
k
⌋
t=\lfloor \frac{n}{k}\rfloor
t=⌊kn⌋ 得到
k
k
k 的取值
[
l
,
r
]
[l,r]
[l,r]
我们可以得到:
{
⌈
a
t
+
1
⌉
≤
x
≤
⌊
a
t
⌋
⌈
b
t
+
1
⌉
≤
y
≤
⌊
b
t
⌋
\begin{cases} \lceil\frac{a}{t+1}\rceil\le x\le \lfloor\frac{a}{t}\rfloor\\ \lceil\frac{b}{t+1}\rceil\le y\le \lfloor\frac{b}{t}\rfloor \end{cases}
{⌈t+1a⌉≤x≤⌊ta⌋⌈t+1b⌉≤y≤⌊tb⌋
{
x
∈
[
⌈
a
t
+
1
⌉
,
⌊
a
t
⌋
]
y
∈
[
⌈
b
t
+
1
⌉
,
⌊
b
t
⌋
]
\begin{cases} x\in[\lceil\frac{a}{t+1}\rceil, \lfloor\frac{a}{t}\rfloor]\\ y\in[\lceil\frac{b}{t+1}\rceil, \lfloor\frac{b}{t}\rfloor] \end{cases}
{x∈[⌈t+1a⌉,⌊ta⌋]y∈[⌈t+1b⌉,⌊tb⌋]
此时
x
+
y
=
k
x+y=k
x+y=k 且
k
∈
[
l
,
r
]
k\in[l,r]
k∈[l,r]
于是
k
∈
[
⌈
a
t
+
1
⌉
+
⌈
b
t
+
1
⌉
,
⌊
a
t
⌋
+
⌊
b
t
⌋
]
k\in[\lceil\frac{a}{t+1}\rceil+\lceil\frac{b}{t+1}\rceil,\lfloor\frac{a}{t}\rfloor+\lfloor\frac{b}{t}\rfloor]
k∈[⌈t+1a⌉+⌈t+1b⌉,⌊ta⌋+⌊tb⌋]
于是满足区间合法的情况下求交即是对答案的贡献
注意数论分块写法
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return f*x;
}
#define MAXN 1000000000
#define INF 0x3f3f3f3f
int main(){
int a=read(),b=read(),n=a+b,ans=0;
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
int t=n/l,al=(a+t)/(1+t),ar=a/t,bl=(b+t)/(1+t),br=b/t;
if(al<=ar&&bl<=br) ans+=max(0,min(r,ar+br)-max(l,al+bl)+1);
}
printf("%d\n",ans);
return 0;
}