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;
}