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;
}

posted @ 2021-12-24 23:31  Bellala  阅读(48)  评论(0)    收藏  举报