Acwing200 Hankson的趣味题

原题面:https://www.acwing.com/problem/content/202/

题目大意:gcd(x,a0)=a1,lcm(x,b0)=b1,问你有多少满足条件的正整数x。

输入描述:t组输入,第一行一个整数t,代表测试数据的组数。接下来t行,每行四个整数,a0,a1,b0,b1。

输出描述:对于每组测试数据,输出满足条件的x的个数。

输入样例:

2
41 1 96 288
95 1 37 1776

输出样例:

6
2

分析:lcm(x,b0)=b1说明x一定是b1的因子,可以预处理跑出1e5范围内的质数,再对b1进行质因子分解,最后dfs枚举b1的因子,去检测是否满足gcd(x,a0)=a1&&lcm(x,b0)=b1,如果满足且不重复,则使答案加一。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
int n;ll a,b,c,d;
map<ll,int> vis;
int v[maxn];ll prime[maxn];int cnt,ans;
vector<ll> divisor;
ll gcd(ll a,ll b) {
    return !b ? a : gcd(b, a % b);
}
ll lcm(ll a,ll b) {
    return a * b / gcd(a, b);
}
void sieve() {
    cnt = 0;
    memset(v, 0, sizeof(v));
    for (int i = 2; i < maxn; i++) {
        if (!v[i]) {
            v[i] = i;
            prime[cnt++] = i;
        }
        for (int j = 0; j < cnt; j++) {
            if (v[i] < prime[j] || i * prime[j] >= maxn) break;
            v[i * prime[j]] = prime[j];
        }
    }
}
void depart(ll d) {
    divisor.clear();
    for (int i = 0; prime[i] * prime[i] <= d; i++) {
        while (d % prime[i] == 0) {
            divisor.push_back(prime[i]);
            d /= prime[i];
        }
    }
    if (d > 1)
        divisor.push_back(d);
}
void dfs(ll x,int p,int n) {
    if (p == n) {
        //cout<<x<<endl;
        if (vis[x]) return;
        vis[x] = 1;
        if (gcd(a, x) == c && lcm(b, x) == d)
            ans++;
        return;
    }
    dfs(x * divisor[p], p + 1, n);
    dfs(x, p + 1, n);
}
//gcd(x,a0)=a1  lcm(x,b0)=b1
int main() {
    sieve();
    cin >> n;
    while (n--) {
        ans = 0;
        vis.clear();
        cin >> a >> c >> b >> d;
        depart(d);
        dfs(1, 0, divisor.size());
        cout << ans << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/SwiftAC/p/12110790.html