【题目描述】:
【题目解法】:
枚举d=gcd(i,j)
ans=sigma(d^d*sigma(i^d)*sigma(j^d)*sigma(mu(k))) 1<=i<=n/d 1<=j<=m/d k|i且k|j
ans=sigma(d^d*sigma(mu(k)*sigma(i^d)*sigma(j^d)*k^d*k^d)) 1<=k<=n/d 1<=i<=n/kd 1<=j<=m/kd1
然后我们O(N)枚举d,然后O(N/d)枚举k并且计算sigma(i^d),然后就可以O(1)的到后面的答案
合并即可,复杂度O(N log N)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=500005;
const long long maxmod=1000000007;
int n,m,mobius[N],tot,prime[N];
bool v[N]; long long val[N],sum[N],ans;
inline long long getint()
{
long long x=0; char c=getchar(); bool flag=false;
while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
if (c=='-') flag=true,c=getchar();
while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
if (flag) return -x; else return x;
}
void init()
{
n=getint(); m=getint(); if (n>m) swap(n,m);
memset(v,true,sizeof(v)); mobius[1]=1;
for (int i=2; i<=n; i++)
{
if (v[i]) prime[++tot]=i,mobius[i]=-1;
for (int j=1; j<=tot; j++)
{
if (i*prime[j]>n) break; v[i*prime[j]]=false;
mobius[i*prime[j]]=-mobius[i];
if (i%prime[j]==0) {mobius[i*prime[j]]=0; break;}
}
}
}
inline long long calc(long long x,long long y)
{
long long nowans=1;
while (y)
{
if (y%2==1) nowans=nowans*x%maxmod;
x=x*x%maxmod; y=y/2;
}
return nowans;
}
void solve()
{
for (int i=1; i<=m; i++) val[i]=1;
for (int i=1; i<=n; i++)
{
for (int j=1; j<=m/i; j++) val[j]=val[j]*j%maxmod;
for (int j=1; j<=m/i; j++) sum[j]=(sum[j-1]+val[j])%maxmod;
long long nowans=0;
for (int j=1; j<=n/i; j++)
{
long long tmp=val[j]*val[j]%maxmod*sum[n/i/j]%maxmod*sum[m/i/j]%maxmod;
nowans=nowans+mobius[j]*tmp%maxmod; nowans=(nowans%maxmod+maxmod)%maxmod;
}
nowans=nowans*calc(i,i)%maxmod;
ans=(ans+nowans)%maxmod;
}
printf("%lld\n",ans);
}
int main()
{
init();
solve();
return 0;
}