# 【bzoj4407】于神之怒加强版 莫比乌斯反演+线性筛

1 2
3 3

20

$\sum\limits_{i=1}^n\sum\limits_{j=1}^m\gcd(i,j)^k\\=\sum\limits_{d=1}^{\min(n,m)}d^k\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=d]\\=\sum\limits_{d=1}^{\min(n,m)}d^k\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}[\gcd(i,j)=1]\\=\sum\limits_{d=1}^{\min(n,m)}d^k\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}\sum\limits_{t|gcd(i,j)}\mu(t)\\=\sum\limits_{d=1}^{\min(n,m)}d^k\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}\sum\limits_{t|i\&t|j}\mu(t)\\=\sum\limits_{d=1}^{\min(n,m)}d^k\sum\limits_{t=1}^{\lfloor\frac{\min(n,m)}d\rfloor}\mu(t)\lfloor\frac n{dt}\rfloor\lfloor\frac m{dt}\rfloor$

$\sum\limits_{d=1}^{\min(n,m)}d^k\sum\limits_{t=1}^{\lfloor\frac{\min(n,m)}d\rfloor}\mu(t)\lfloor\frac n{dt}\rfloor\lfloor\frac m{dt}\rfloor\\=\sum\limits_{D=1}^{\min(n,m)}\lfloor\frac nD\rfloor\lfloor\frac mD\rfloor\sum\limits_{d|D}d^k\mu(t)\\=\sum\limits_{D=1}^{\min(n,m)}\lfloor\frac nD\rfloor\lfloor\frac mD\rfloor f(D)\\(f(D)=\sum\limits_{d|D}d^k\mu(t))$

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 5000010
using namespace std;
typedef long long ll;
const int p = 5000000 , mod = 1000000007;
int prime[N] , tot;
ll d[N] , f[N] , sum[N];
bool np[N];
ll pow(ll x , ll y)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
int main()
{
int T , k , i , j , n , m;
ll ans;
scanf("%d%d" , &T , &k);
f[1] = sum[1] = 1;
for(i = 2 ; i <= p ; i ++ )
{
if(!np[i]) prime[++tot] = i , d[tot] = pow(i , k) , f[i] = (d[tot] - 1 + mod) % mod;
for(j = 1 ; j <= tot && i * prime[j] <= p ; j ++ )
{
np[i * prime[j]] = 1;
if(i % prime[j] == 0)
{
f[i * prime[j]] = f[i] * d[j] % mod;
break;
}
else f[i * prime[j]] = f[i] * f[prime[j]] % mod;
}
sum[i] = (sum[i - 1] + f[i]) % mod;
}
while(T -- )
{
scanf("%d%d" , &n , &m) , ans = 0;
for(i = 1 ; i <= n && i <= m ; i = j + 1)
j = min(n / (n / i) , m / (m / i)) , ans = (ans + (ll)(n / i) * (m / i) % mod * (sum[j] - sum[i - 1] + mod)) % mod;
printf("%lld\n" , ans);
}
return 0;
}


|转载请注明 [原文链接][作者] ，谢谢！

posted @ 2017-08-05 09:28  GXZlegend  阅读(240)  评论(0编辑  收藏  举报