【数论推导】Educational Codeforces Round 106 Problem D: The Number of Pairs

D-The Number of Pairs

传送门
【数论推导】Educational Codeforces Round 106 Problem D: The Number of Pairs_第1张图片
题目大意:
给定 c , d , x c,d,x c,d,x, 找出有多少对正整数对 ( a , b ) (a,b) (a,b) 满足下述等式:
c • l c m ( a , b ) − d • g c d ( a , b ) = x c•lcm(a,b)-d•gcd(a,b)=x clcm(a,b)dgcd(a,b)=x
解题思路:
c • l c m ( a , b ) − d • g c d ( a , b ) = x ; l c m ( a , b ) = a • b g c d ( a , b ) ; c • a • b g c d ( a , b ) − d • g c d ( a , b ) = x ; c•lcm(a,b)-d•gcd(a,b)=x;\\ lcm(a,b)=\frac{a•b}{gcd(a,b)};\\ \frac{c•a•b}{gcd(a,b)}-d•gcd(a,b)=x; clcm(a,b)dgcd(a,b)=x;lcm(a,b)=gcd(a,b)ab;gcd(a,b)cabdgcd(a,b)=x;
g = g c d ( a , b ) g = gcd(a,b) g=gcd(a,b),则有 a = k 1 • g a=k_1•g a=k1g, b = k 2 • g b=k_2•g b=k2g
c • k 1 • k 2 • g − d • g = x ; g • ( c • k 1 • k 2 − d ) = x ; g = x c • k 1 • k 2 − d ; c•k_1•k_2•g-d•g=x;\\ g•(c•k_1•k_2-d)=x;\\ g=\frac{x}{c•k_1•k_2-d}; ck1k2gdg=x;g(ck1k2d)=x;g=ck1k2dx;
其中 g ∈ N + g∈N^+ gN+,即 ( c • k 1 • k 2 − d )   ∣   x ; (c•k_1•k_2-d)\ |\ x; (ck1k2d)  x; (符号解释: x ∣ y x|y xy 指的是 x x x 可以整除 y y y,即 y y y % x = = 0 x==0 x==0)
由此可以想到枚举 x x x 的约数来求解;假设其中的一个约数为 y y y;
y = c • k 1 • k 2 − d ; k 1 • k 2 = y + d c ; y=c•k_1•k_2-d;\\ k_1•k_2=\frac{y+d}{c}; y=ck1k2d;k1k2=cy+d;
在约数 y y y 确定的情况下, g g g的值也是确定的,因 a = k 1 • g a=k_1•g a=k1g, b = k 2 • g b=k_2•g b=k2g,所以 k 1 k_1 k1 k 2 k_2 k2 的值和 a 与 b a与b ab的值是一 一对应的,因此可通过计算 ( k 1 , k 2 ) (k_1,k_2) (k1,k2)的对数来间接计算 ( a , b ) (a,b) (a,b)的对数。
g c d ( a , b ) = g gcd(a,b)=g gcd(a,b)=g, k 1 k_1 k1 k 2 k_2 k2互质。令 m = y + d c m=\frac{y+d}{c} m=cy+d ;
问题: 需要求有多少对互质的正整数的乘积是 m m m
算术基本定理:任何一个大于1的自然数 N N N, 如果 N N N 不为质数,那么 N N N 可以唯一分解成有限个质数的乘积。
m m m 可以表示为: m = p 1 c 1 • p 2 c 2 • . . . • p n c n m=p_1^{c_1}•p_2^{c_2}•...•p_n^{c_n} m=p1c1p2c2...pncn
任意两个质数之间是互质的, 1 1 1与任意的正整数都是互质的。
很明显相同的质因子不能同时出现在 k 1 k_1 k1 k 2 k_2 k2 中,则可按照质因数种类数将其化分为 n n n 类,对于每一类数要么全部放入 k 1 k_1 k1中,要么全部放入 k 2 k_2 k2中。因质数之间互质,固质数的幂之间同样是互质的,所以以这种形式划分是合理的。每一类都有两种选择,一共有 n n n类,所以总的方案数为 2 n 2^n 2n种。
综上所述,本题的答案即为: a n s w e r = ∑ y ∣ x g e t ( y ) answer=\displaystyle\sum_{y|x}{get(y)} answer=yxget(y).
g e t 函 数 get函数 get:传入参数 y y y ,计算出 y + d c \frac{y+d}{c} cy+d的质因子个数 c n t cnt cnt,返回 2 c n t 2^{cnt} 2cnt;
分析一下时间复杂度,线性筛O(n),枚举约数 n \sqrt{n} n ,t次询问, g e t get get函数O( n l o g   n \sqrt{\frac{n}{log\ n}} log nn ),总的时间复杂度O( n + t n+t n+t n \sqrt{n} n n l o g   n \sqrt{\frac{n}{log\ n}} log nn ), t ∈ 1 e 4. n ∈ 1 e 7 t∈1e4.n∈1e7 t1e4.n1e7,很明显时间复杂度很大。接下来考虑优化。
每一个数的质因子个数可以在线性筛中维护,具体维护方法请参考代码。因此get函数即可O(1)的时间复杂度来实现。
总的时间复杂度O( n + t • n n+t•\sqrt{n} n+tn ),大约是O(4e7),在2s的时间限制内完全可以过掉。

上代码:

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 20000010;
ll c, d, x;
ll prime[N], cnt;
ll vis[N];
void get_prime()
{
     
    for (int i = 2;i < N;i++)
    {
     
        if (!vis[i]) prime[cnt++] = i, vis[i] = 1;
        for (int j = 0;prime[j] <= N / i;j++)
        {
     

            if (i % prime[j] == 0)
            {
     
                vis[prime[j] * i] = vis[i];
                break;
            }
            else {
     
                vis[prime[j] * i] = vis[i] + 1;
            }
        }

    }
}
ll qpow(ll a, ll b)
{
     
    ll res = 1;
    while (b)
    {
     
        if (b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}
ll get(ll i)
{
     
    if ((i + d) % c) return 0;
    int m = (i + d) / c;
    return qpow(2, vis[m]);
}
int main()
{
     
    int t;cin >> t;
    get_prime();
    while (t--)
    {
     
        cin >> c >> d >> x;
        ll ans = 0;
        for (int i = 1;i <= x / i;i++)
        {
     
            if (x % i == 0)
            {
     
                ans += get(i);
                if (x / i != i) ans += get(x / i);
            }
        }
        cout << ans << endl;
    }
    return 0;
}

参考文献

你可能感兴趣的:(数论,Codeforce)