Hankson的趣味题 (算法竞赛进阶指南,约数)

一.题目链接:

计蒜客 - T2094

二.题目大意:

已知 (a0, x) = a1, [b0, x] = b1

求满足上式 x 解的个数.

三.分析:

因为 [b0, x] = b1,所以 x 为 b1 的约数

又 b1 最多只有 10 个质因子,所以我们可以考虑 x 的质因子组成.

当前正在考虑质因子 p

设 m[0] 表示 a0 含 p 的个数,m[1] 表示 a1 含 p 的个数,

     m[2] 表示 b0 含 p 的个数,m[3] 表示 b1 含 p 的个数,ans 表示 x 含 p 的个数.

若 m[0] < m[1], 则 ans 无解;若 m[0] == m[1], 则 ans >= m[1];若 m[0] > m[1], 则 ans == m[1].

若 m[2] < m[3], 则 ans == m[3];若 m[2] == m[3], 则 ans <= m[1];若 m[2] > m[3], 则 ans 无解.

因此只需打出素数表然后枚举素数即可.

注意:1. 如果 b1 % prime[i],应该 continue,因为 b1 最多只有 10 个不同的质因子,这样可以剪去绝大多数情况.

           2. 枚举完所有素数后,若 b1 > 1,即 b1 是质数,应再计算 b1 因子的方案数.

四.代码实现:

#include <bits/stdc++.h>
using namespace std;

const int M = (int)45000;

int prime[M + 5], cnt;
bool is_prime[M + 5];

int a0, a1, b0, b1;

void get_prime()
{
    cnt = 0;
    memset(is_prime, 1, sizeof(is_prime));
    is_prime[0] = is_prime[1] = 0;
    for(int i = 1; i <= M; ++i)
    {
        if(is_prime[i]) prime[++cnt] = i;
        for(int j = 1; j <= cnt && i * prime[j] <= M; ++j)
        {
            is_prime[i * prime[j]] = 1;
            if(i % prime[j] == 0)   break;
        }
    }
}

void divide(int& m, int& n, int p)
{
    m = 0;
    while(n % p == 0)
    {
        m++;
        n /= p;
    }
}

int work(int p)
{
    int m[4], ans = 1;
    divide(m[0], a0, p);
    divide(m[1], a1, p);
    divide(m[2], b0, p);
    divide(m[3], b1, p);
    if(m[0] == m[1] && m[2] == m[3] && m[1] <= m[3])        return m[3] - m[0] + 1;
    else if(m[0] == m[1] && m[2] < m[3] && m[1] <= m[3])    return 1;
    else if(m[0] > m[1] && m[2] < m[3] && m[1] == m[3])     return 1;
    else if(m[0] > m[1] && m[2] == m[3] && m[1] <= m[3])    return 1;
    else                                                    return 0;
}

int main()
{
    get_prime();
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d %d %d", &a0, &a1, &b0, &b1);
        int ans = 1;
        for(int i = 1; i <= cnt && prime[i] <= b1; ++i)
        {
            if(b1 % prime[i])               continue;
            if(!(ans *= work(prime[i])))    break;
        }
        if(b1 > 1)  ans *= work(b1);
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/The___Flash/article/details/104212323