bzoj3561(莫比乌斯反演)

传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3561
题面:
给定 n , m n,m
i = 1 n j = 1 m l c m ( i , j ) g c d ( i , j ) \sum_{i=1}^n\sum_{j=1}^m lcm(i,j)^{gcd(i,j)}


s o l u t i o n solution
比较简单的莫比乌斯反演吧
直接推式子就完事了(假定 m n m\le n )
i = 1 n j = 1 m ( i j g c d ( i , j ) ) g c d ( i , j ) = d = 1 m d d i = 1 n d j = 1 m d ( i j ) k [ g c d ( i , j ) = = 1 ] = d = 1 m d d t = 1 m d μ ( t ) t 2 d i = 1 n t d i d j = 1 m t d j d \sum_{i=1}^n\sum_{j=1}^m\left( \frac{ij}{gcd(i,j)} \right)^{gcd(i,j)}\\ =\sum_{d=1}^md^d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{d}\rfloor}(ij)^k[gcd(i,j)==1]\\ =\sum_{d=1}^md^d\sum_{t=1}^{\lfloor\frac{m}{d}\rfloor}\mu(t)t^{2d}\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}i^d\sum_{j=1}^{\lfloor\frac{m}{td}\rfloor}j^d
直接预处理就好了
复杂度 O ( n l o g n ) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back 
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
#define N 500000
int rd()
{
	int num = 0;char c = getchar();bool flag = true;
	while(c < '0'||c > '9') {if(c == '-') flag = false;c = getchar();}
	while(c >= '0' && c <= '9') num = num*10+c-48,c = getchar();
	if(flag) return num;else return -num;
}
const int p = 1e9+7;
int n,m;
int v[500100],sum[500100];
int prime[500100],miu[500100];
bool flag[500100];
inline int mul(int a,int b){return 1ll*a*b%p;}
inline int calc(int a,int b){return (a+=b)>=p?a-=p:a;}
inline int ksm(int a,int x){int now=1;for(;x;x>>=1,a=1ll*a*a%p)if(x&1)now=1ll*now*a%p;return now;}
int main()
{ 
    n = rd();m = rd();miu[1] = 1;
    if(n<m) swap(n,m);
    rep(i,2,N)
    {
    	if(!flag[i]) prime[++prime[0]] = i,miu[i] = p-1;
    	rep(j,1,prime[0])
    	{
    		if(i*prime[j]>N) break;
    		flag[i*prime[j]] = true;
    		if(i%prime[j] == 0) break;
    	    miu[i*prime[j]] = p-miu[i];
		}
    }
    rep(i,1,n) v[i] = 1,sum[i] = calc(sum[i-1],v[i]);
    int ans = 0;
	rep(d,1,m)
	{
		int sigma = 0;
		rep(i,1,n/d) v[i] = mul(v[i],i),sum[i] = calc(sum[i-1],v[i]);
	    rep(t,1,m/d) 
		     miu[t] = mul(miu[t],mul(t,t)),
			 sigma = calc( sigma , mul( miu[t] , mul( sum[n/(t*d)] , sum[m/(t*d)] ) ) );
	    ans = calc(ans,mul(sigma,ksm(d,d)));
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1035719430/article/details/85069613
今日推荐