CF EDU 106 D - The Number of Pairs
D - The Number of Pairs
数论,线性筛
给定 \(c,d,x\) 求满足 \(c*[a,b]-d*(a,b)=x\) 的 \((a,b)\) 对数 (当 \(a\neq b\) 时,\((a,b),(b,a)\) 算两对)
记 \(lcm=[a,b],\;gcd=(a,b)\)
\(a'=\frac a{gcd}\;b'=\frac b{gcd}\)
\(lcm=\frac {a*b}{gcd}=\frac {a'*b'*gcd*gcd}{gcd}=a'*b'*gcd\)
因此
\(c*a'*b'*gcd-d*gcd=x\)
\(gcd=\frac x{c*a'*b'-d}\)
所以 \(gcd\) 是 \(x\) 的因子,\(O(\sqrt x)\) 枚举 \(x\) 的因子 \(y=c*a'*b'-d\)
\(a'*b'=\frac {y+d}c\) , 此时 \(\frac {y+d}c\) 为常数,记为 \(t\)
因为 \(a'\) 与 \(b'\) 互质,所以将 \(t\) 标准分解后,\(t\) 有 \(cnt\) 种素因子,则 \((a',b')\) 对数有 \(2^{cnt}\) 个(一种素因子要么在 \(a'\), 要么在 $b' $)
但标准分解 \(t\) 太慢,设 \(f[t]\) 为 \(t\) 有几种素因子,可以发现 \(f\) 有类似积性函数的递推关系:
- \(f[p]=1\)
- \(p\nmid i,\;f[i*p]=f[i]+1\)
- \(p\mid i,\; f[i*p]=f[i]\)
因此可利用线性筛预处理出 \(f[t]\)
注意 \(t=\frac {y+d}c\), 范围为 \(2e7\) 而非 \(1e7\), 要线性筛预处理到 \(2e7\)
CF EDU 106 D - The Number of Pairs
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 2e7 + 10;
int pr[N], f[N], cnt;
bool st[N];
ll qmi(ll a, ll b)
{
ll ans = 1;
while(b)
{
if (b & 1)
ans *= a;
b >>= 1;
a *= a;
}
return ans;
}
void get_primes(int n)
{
memset(st, true, sizeof st);
st[1] = false;
f[1] = 0;
for (int i = 2; i <= n; i++)
{
if (st[i])
{
pr[++cnt] = i;
f[i] = 1;
}
for (int j = 1; j <= cnt && pr[j] <= n / i; j++)
{
int p = pr[j];
st[i * p] = false;
if (i % p == 0)
{
f[i * p] = f[i];
break;
}
else
f[i * p] = f[i] + 1;
}
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
get_primes(N - 10);
int T;
cin >> T;
while(T--)
{
int c, d, x;
cin >> c >> d >> x;
vector<int> factor;
for (int i = 1; i <= x / i; i++)
{
if (x % i)
continue;
factor.push_back(i);
if (i != x / i)
factor.push_back(x / i);
}
ll ans = 0;
for (int y : factor)
{
if ((y + d) % c)
continue;
int t = (y + d) / c;
ans += qmi(2, f[t]);
}
cout << ans << endl;
}
return 0;
}