Codeforces 1499 D. The Number of Pairs(数学推导+埃氏筛)

传送门


题目大意

给定 c , d , x c,d,x c,d,x,求出满足 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 ( a , b ) (a,b) (a,b)的对数。

解题思路

差一点就写出来了,以为欧拉筛最小质因子的质因数分解可以过结果却被卡TLE了,忘记了埃氏筛同样可以预处理。

首先是推导式子,这种式子的下手点一般就是根据都是正整数,那么转化过程中涉及到除法的式子一定可以整除。设 g c d ( a , b ) = g gcd(a,b) = g gcd(a,b)=g,那么:

c ∗ a ∗ b g − d ∗ g = x c ∗ a ∗ b g = x + d ∗ g c = d ∗ g + x a ∗ b g c*\frac{a*b}{g} - d*g = x \\ c*\frac{a*b}{g} = x + d*g \\ c = \frac{d*g+x}{\frac{a*b}{g}} cgabdg=xcgab=x+dgc=gabdg+x

最终化为了: c = d + x g a g ∗ b g c = \frac{d + \frac{x}{g}}{\frac{a}{g}*\frac{b}{g}} c=gagbd+gx,根据上面所说, c c c是整数那么等号右边的中间结果都是整数,因此 g ∣ x g|x gx;然后又可以观察到分母是两个互质的数的乘积,实际上答案已经浮出水面了,就是枚举 x x x的所有因数 g g g,设求出 d + x g c \frac{d + \frac{x}{g}}{c} cd+gx能被分成 m m m对互质的数的乘积,实际上 m m m就是该数的质因子的种类数,根据二项式定理得出贡献的对数为 2 m 2^m 2m

但是我写了常数时间复杂度分解质因数的算法被卡了,具体原因不太清楚;可能是欧拉筛写多了,实际上在埃氏筛的第二层循环不就可以对每个数累加质因子的种类数吗,这样预处理的时间复杂度为 O ( 2 e 7 ∗ l o g l o g 2 e 7 ) O(2e^7*loglog2e^7) O(2e7loglog2e7),至于因数分解直接 O ( x ) O(\sqrt{x}) O(x )即可。


//
// Created by Happig on 2021/3/20.
//
#include <bits/stdc++.h>
#include <unordered_map>

using namespace std;
#define ENDL "\n"
#define lowbit(x) (x & (-x))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e7 + 10;

int num[maxn];
bitset<maxn> vis;

void init() {
    
    
    for (int i = 2; i < maxn; i++) {
    
    
        if (!vis[i]) {
    
    
            num[i] = 1;
            for (int j = i + i; j < maxn; j += i) {
    
    
                vis[j] = 1;
                num[j]++;
            }
        }
    }
}

vector<int> fac;


int main() {
    
    
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int T;
    int c, d, x;
    init();
    cin >> T;
    while (T--) {
    
    
        cin >> c >> d >> x;
        fac.clear();
        for (int i = 1; i * i <= x; i++) {
    
    
            if (x % i == 0) {
    
    
                int j = x / i;
                if (i == j) fac.push_back(i);
                else fac.push_back(i), fac.push_back(j);
            }
        }
        ll ans = 0;
        for (auto g:fac) {
    
    
            int sum = d + x / g;
            if (sum % c) continue;
            ans += 1LL << num[sum / c];
        }
        cout << ans << ENDL;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/115054744