CF1202F You Are Given Some Letters... 题解
Link
P.S.
有意思的好题。
Description.
好的字符串定义为其满足有 \(a\) 个 a
,\(b\) 个 b
。
求所有好的字符串有多少种可能的不同循环节。
\[a,b\le 10^9
\]
Solution.
下文设 \(k\) 为循环节数量,\(a_1\) 和 \(b_1\) 分别表示一个循环节内有多少 a
和 b
\[k\times a_1\le a\le (k+1)\times a_1
\]
\[k\times b_1\le b\le (k+1)\times b_1
\]
\[\therefore \left\lfloor\frac {a+k}{k+1}\right\rfloor\le a_1\le\left\lfloor\frac ak\right\rfloor
\]
\[\therefore \left\lfloor\frac {b+k}{k+1}\right\rfloor\le b_1\le\left\lfloor\frac bk\right\rfloor
\]
同时也有
\[\left\lfloor\frac{a+b+k}{k+1}\right\rfloor\le a_1+b_1\le\left\lfloor\frac{a+b}k\right\rfloor
\]
\[len=a_1+b_1
\]
所以只需要整除分块就可以了
Coding.
//我是一发子弹,子弹没有感情,因此,没有迷茫,只会飞向目标。{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
x=0;char c=getchar(),f=0;
for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
f?x=-x:x;
}/*}}}*/
int a,b,n;ll rs=0;
int main()
{
read(a),read(b),n=a+b;
for(int l=1,r,k;l<=n;l=r+1)
{
k=n/l,r=n/k;if(a<k||b<k) continue;
int la=(a+k)/(k+1),ra=a/k,lb=(b+k)/(k+1),rb=b/k;
if(la<=ra&&lb<=rb) rs+=max(0,min(r,rb+ra)-max(l,la+lb)+1);
}
return printf("%lld\n",rs),0;
}