通过这道题,我才知道 积性函数 可以通过 线性筛 来筛。
题目就是就是一道 莫比乌斯 模板题的加强
原来那倒题是ΣΣgcd(i, j) 现在变成了 ΣΣ(gcd(i,j)^k % mod)
令x = gcd(i, j) f(x) = x ^ k;
原式: ΣΣf(x)
令 f = g (卷积) 1
则g = f (卷积) u
推出
--------------------------------------------------------------------------------
以前我是通过 暴力枚举 d 然后再 枚举 x = d * i 来先求出g(x)
不过这道题直接TLE (nlogn * 快速幂)
--------------------------------------------------------------------------------
于是线性筛
因为积性函数 设 m , n 互质 则 g(mn) = g(m) * g(n)
对于 m n 不互质的 现在来解决:
对于任何 x (把x分解质因子)
推出 =>
得出
那么
那么
对于在线性筛中 会有 而
故
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 5000000;
const int mod = 1000000000 + 7;
LL gxx[maxn + 5];
int pri[maxn + 5];
int miu[maxn + 5];
bool vis[maxn + 5];
int max_id;
int T, K;
bool chk1 = 0;
bool chk2 = 1;
bool chk3 = 1;
LL GetPw(LL n, LL k)
{
LL res = 1;
while(k)
{
if(k & 1) res *= n, res %= mod;
n *= n;
k >>= 1;
n %= mod;
}
return res;
}
void GetMuGx()
{
miu[1] = 1;
vis[1] = 1;
gxx[1] = 1;
for(int ii = 2;ii <= maxn;ii++)
{
if(!vis[ii])
{
miu[ii] = -1;
gxx[ii] = -1 + GetPw(ii, K);
pri[++max_id] = ii;
}
for(int i = 1;i <= max_id;i++)
{
int xx = pri[i] * ii;
if(xx > maxn) break;
vis[xx] = 1;
if(ii % pri[i] == 0)
{
miu[xx] = 0;
gxx[xx] = gxx[ii] * (gxx[pri[i]] + 1) % mod;
break;
}
else
{
miu[xx] = -miu[ii];
gxx[xx] = gxx[ii] * gxx[pri[i]] % mod;
}
}
}
for(int i = 1;i <= maxn;i++) gxx[i] += gxx[i - 1], gxx[i] %= mod;
}
int main()
{
scanf("%d%d", &T, &K);
GetMuGx();
if(chk1) printf("test pw: %d\n", (int)GetPw(2, 5000000));
if(chk1) for(int i = 4999900;i <= 4999910;i++) printf("gxx[%d] = %lld\n", i, gxx[i]);
while(T--)
{
LL res = 0;
int m, n, mm;
scanf("%d%d", &m, &n);
mm = min(m, n);
for(int ii = 1, last;ii <= mm;ii = last + 1)
{
last = min(n / (n / ii), m / (m / ii));
res += ((gxx[last] - gxx[ii - 1]) % mod) * (((LL)n / ii) * ((LL)m / ii) % mod) % mod;
res %= mod;
}
res = (res + mod) % mod;
printf("%lld\n", res);
}
return 0;
}