【CF1499D】The Number of Pairs
题目
题目链接:https://codeforces.com/contest/1499/problem/D
给定 \(c,d,x\),求有多少二元组 \((a,b)\) 满足
\(Q\leq 10^4;1\leq c,d,x\leq 10^7\)。
思路
因为 \(\text{lcm}(a,b)\) 一定是 \(\gcd(a,b)\) 的倍数,所以等号左边一定是 \(\gcd(a,b)\) 的倍数,那么 \(\gcd(a,b)\) 必然是 \(x\) 的因子。
那么枚举 \(x\) 的所有因子 \(i\),就可以得到对应的 \(\gcd(a,b)=i,\text{lcm}(a,b)=\frac{x+di}{c}\)。
设 \(a=\gcd(a,b)\times p_1^{a_1}\times p_2^{a_2}\times \cdots,b=\gcd(a,b)\times q_1^{b_1}\times q_2^{b_2}\times \cdots\),那么 \(\text{lcm}(a,b)=\gcd(a,b)\times p_1^{a_1}\times p_2^{a_2}\times \cdots\times q_1^{b_1}\times q_2^{b_2}\cdots\)。
也就是对于 \(k=\frac{\text{lcm}(a,b)}{\gcd(a,b)}\) 的每一个质因子,我们分配到 \(a\) 中或者 \(b\) 中都是一种合法方案。记 \(x\) 的止因子数量为 \(f(x)\),那么方案数就是 \(2^{f(k)}\)。
那么直接预处理出 \(1\sim 2\times 10^7\) 所有数的最大质因子,然后就可以预处理出 \(f(x)\) 了。
时间复杂度 \(O(n\log \log n+Q\sqrt{x})\),其中 \(n=\max(c,d)\leq 10^7\)。
代码
VP 的时候数组一开始只开到了 \(10^7\) 调了半天。。。
#include <bits/stdc++.h>
#define mp make_pair
#define ST first
#define ND second
using namespace std;
typedef long long ll;
typedef long double ld;
const int N=20000010;
int Q,m,c,d,x,prm[N],f[N],v[N];
ll ans;
bool vis[N];
void findprm(int n)
{
for (int i=2;i<=n;i++)
{
if (!vis[i]) prm[++m]=i;
for (int j=1;j<=m;j++)
{
if (n/prm[j]<i) break;
vis[i*prm[j]]=1;
}
}
for (int i=1;i<=m;i++)
for (int j=prm[i];j<=n;j+=prm[i])
v[j]=prm[i];
}
void calc(ll g)
{
ll l=x+g*d;
if (l%(1LL*c)) return;
l=l/(1LL*c);
if (l%g) return;
ans=ans+(1LL<<f[l/g]);
}
signed main()
{
findprm(N-1);
for (int i=2;i<N;i++)
{
int p=i;
while (!(p%v[i])) p/=v[i];
f[i]=f[p]+1;
}
scanf("%d",&Q);
while (Q--)
{
scanf("%d%d%d",&c,&d,&x);
ans=0;
for (int i=1;i*i<=x;i++)
if (!(x%i))
{
calc(i);
if (i*i!=x) calc(x/i);
}
cout<<ans<<endl;
}
return 0;
}