题目链接:
HDU 4746 Mophues
题意:
令gcd(a,b)=d,对d质因子分解得到质因子个数为k如果k≤C,则称k为C的lucky数字,给出n,m,p,求a∈[1,n],b∈[1,m]使得gcd(a,b)是p的lucky数字的数字对(a,b)有多少对?
分析:
令
d=gcd(i,j)
,我们枚举
d
,对于每个
但是因为
d
需要满足
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <string>
using namespace std;
typedef long long ll;
const int MAX_N = 500010;
const int SZ = 25;
int prime_cnt, prime[MAX_N], factor_num[MAX_N];
ll mu[MAX_N], sum[MAX_N][SZ];
bitset<MAX_N> bs;
void GetMu()
{
prime_cnt = 0;
bs.set();
mu[1] = 1;
for(int i = 2; i < MAX_N; ++i) {
if(bs[i]) {
prime[prime_cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < prime_cnt && i * prime[j] < MAX_N; ++j) {
bs[i * prime[j]] = 0;
if(i % prime[j]) {
mu[i * prime[j]] = -mu[i];
}else {
mu[i * prime[j]] = 0;
break;
}
}
}
int MAX_SZ = 0;
for(int i = 0; i < prime_cnt; ++i ) {
for(int j = prime[i]; j < MAX_N; j += prime[i]) {
int x = j, tmp = 0;
while(x % prime[i] == 0) {
x /= prime[i];
tmp++;
}
factor_num[j] += tmp;
MAX_SZ = max(MAX_SZ, factor_num[j]);
}
}
//MAX_SZ = 18
for(int i = 1; i < MAX_N; ++i) {
for(int j = i; j < MAX_N; j += i){
sum[j][factor_num[i]] += mu[j / i];
}
}
for(int i = 1; i < MAX_N; ++i) {
sum[i][0] +=sum[i - 1][0];
for(int j = 1; j < SZ; ++j) {
sum[i][j] += (sum[i - 1][j] + sum[i][j- 1] - sum[i - 1][j - 1]);
}
}
}
inline ll solve(int n, int m, int p)
{
ll ans = 0;
int top = min(n, m), last;
for(int i = 1; i <= top; i = last + 1){
last = min(n / (n / i), m / (m / i));
ans += (sum[last][p] - sum[i - 1][p]) * (n / i) * (m / i);
}
return ans;
}
int main()
{
GetMu();
int T, n, m, p;
scanf("%d", &T);
while(T--) {
scanf("%d%d%d", &n, &m, &p);
if(p >= 20) printf("%lld\n", (ll)n * m);
else printf("%lld\n", solve(n, m, p));
}
return 0;
}