SPOJ PROD1GCD - Product it again

SPOJ PROD1GCD

Description
he problem is very simple. given two integers n and m, find the product GCD(1, 1) * GCD(1, 2) * … * GCD(1, M) * GCD(2, 1) * GCD(2, 2) * … * GCD(2, M) * … * GCD(N, 1) * GCD(N, 2) * … * GCD(N, M).

Input
The first line will be the number of test cases t, followed by t lines , each having two numbers n and m (1 <= n, m <= 10000000) (1 <= t <= 5).

Output
Output the required solution modulo 10^9+7.

Example
Input
1
5 6
Output
5760

题意:给出N,M,求GCD(1, 1) * GCD(1, 2) * … * GCD(1, M) * GCD(2, 1) * GCD(2, 2) * … * GCD(2, M) * … * GCD(N, 1) * GCD(N, 2) * … * GCD(N, M)。

思路:某人告诉我,找规律,统计质数就行。

考虑某一个质数p对答案的贡献为p^((n/p * m/p) + ((n/p^2 * m/p^2)) + ….)
原理类比n!的质因子分解后,对某个质因子p的指数大小的计数。
所以我们只需要一个线性筛即可,然后暴力计数。

#include
#include
#include

using namespace std;

typedef long long LL;
const LL mod = 1e9+7;
const LL maxn = 10000000 + 5;
bool vis[maxn]; //标记是否访问过某个数
LL p[maxn/10]; //记录最大范围内的所有素数
LL cnt;

void GetPrime()//找出最大范围内的所有素数
{
    memset(vis,0,sizeof(vis));
    cnt = 0;
    for(LL i = 2; i < maxn; i++){
        if(!vis[i]){
            p[cnt++] = i;
        }
        for(LL j = 0; j < cnt && p[j] * i < maxn; j++){
            vis[i * p[j]] = 1;
            if(i % p[j] == 0) break;
        }
    }
}

LL Pow(LL a, LL b)
{
    LL res = 1;
    while(b) {
        if(b & 1) {
            res *= a;
            res %= mod;
        }
        a *= a;
        a %= mod;
        b >>= 1;
    }
    return res;
}

int main()
{
    GetPrime();
    LL t,n,m;
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&m);
        LL res = 1;
        if(n > m) swap(n, m);

        for(LL i = 0 ;i < cnt && p[i] <= n; i++){
            LL tmp = p[i];
            LL pn = 0;
            while(tmp <= n){ //求p[i]的指数
                pn += (n/tmp) * (m/tmp);
                tmp *= p[i];
            }
            res *= Pow(p[i], pn);
            res %= mod;
        }
        printf("%lld\n",res);
    }
    return 0;
}

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