cf1499 D. The Number of Pairs(数论,dp,筛法)
题意:
给定正整数 \(c,d,x\),问有多少对 \((a,b)\) 满足 \(c\cdot lcm(a,b)-d\cdot gcd(a,b)=x\)
\(1\le c,d,x\le 1e7\)
思路:
记 \(g=gcd(a,b)\),则 \(a=Ag,b=Bg\),\(A\) 与 \(B\) 互质。
则 \(lcm(a,b)=ab/g=ABg\),原式化为 \((c\cdot AB-d)g=x\)
\(x\) 是 \(g\) 的倍数。枚举 \(x\) 的所有因子 \(g'\),看是否存在整数 \(AB=\frac{x/g'+d}c\)
下面找有几对 \((A,B)\)。考虑 \(AB\) 的质因子分解形式,则 \(A\) 与 \(B\) 不可能有任何一个相同的质因子,那么 \((A,B)\) 对的数量为 \(2^{AB的不同质因子数}\)
设 \(f(x)\) 为 \(x\) 的不同质因子数,可以用类似埃氏筛的做法预处理出所有 \(f(x)\)
还可以更快:用线性筛法递推求 \(f(x)\)。设 \(p\) 为质数,则 \(f(p)=1\);如果 \(i\) 是 \(p\) 的倍数则 \(f(i*p)=f(i)\),否则 \(f(i*p)=f(i)+1\)
线性筛500ms,埃氏筛1000ms
注意 \(AB\) 可能取到 2e7
#include <bits/stdc++.h>
using namespace std;
const int N = 2e7 + 5;
int f[N];
void init_aishi() //埃氏筛
{
for(int i = 2; i < N; i++) if(!f[i])
for(int j = i; j < N; j += i) f[j]++;
}
int pri[N], cnt;
void init_euler(int n) //线性筛
{
for(int i = 2; i <= n; i++)
{
if(!f[i]) pri[cnt++] = i, f[i] = 1;
for(int j = 0; pri[j] <= n / i; j++)
{
if(i % pri[j] == 0)
{
f[i*pri[j]] = f[i];
break;
}
f[i*pri[j]] = f[i] + 1;
}
}
}
signed main()
{
init_euler(N - 3);
int T; cin >> T; while(T--)
{
int c, d, x; cin >> c >> d >> x;
long long ans = 0;
for(int g = 1; g <= sqrt(x); g++)
{
if(x % g) continue;
if((g + d) % c == 0)
{
int AB = (g + d) / c;
ans += (1ll << f[AB]);
}
if(g * g == x) continue;
if((x/g + d) % c == 0)
{
int AB = (x/g + d) / c;
ans += (1ll << f[AB]);
}
}
cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号