bzoj 4176

$\sum_{i=1}^{n}\sum_{j=1}^{n}d(ij)$

$\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{p|i}\sum_{q|j}[gcd(p,q)\equiv 1]$

$\sum_{p=1}^{n}\sum_{q=1}^{n}[gcd(p,q)\equiv 1]\sum_{p|i}\sum_{q|j}1$

$\sum_{p=1}^{n}\sum_{q=1}^{n}[gcd(p,q)\equiv 1]\frac{n}{p}\frac{n}{q}$

$\sum_{p=1}^{n}\sum_{q=1}^{n}\sum_{t|gcd(p,q)}\mu(t)\frac{n}{p}\frac{n}{p}$

$\sum_{t=1}^{n}\mu(t)\sum_{p=1}^{\frac{n}{t}}\frac{n}{pt}\sum_{q=1}^{\frac{n}{t}}\frac{n}{qt}$

设$f(n)=\sum_{i=1}^{n}\frac{n}{i}$，那么后面就可以变成$\sum_{t=1}^{n}\mu(t)f(\frac{n}{t})^{2}$

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#define ll long long
using namespace std;
const ll mode=1000000007;
map <ll,ll> S;
int mu[10000005];
ll s[10000005];
int pri[10000005];
int cnt=0;
bool used[10000005];
void init()
{
mu[1]=s[1]=1;
for(int i=2;i<=10000000;i++)
{
if(!used[i])pri[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*pri[j]<=10000000;j++)
{
used[i*pri[j]]=1;
if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
mu[i*pri[j]]=-mu[i];
}
s[i]=(s[i-1]+mu[i]+mode)%mode;
}
}
ll get_S(ll x)
{
if(x<=10000000)return s[x];
else if(S.find(x)!=S.end())return S[x];
ll ret=0;
int las=0;
for(int i=2;i<=x;i=las+1)
{
las=x/(x/i);
ll temp=get_S(x/i);
ret=(ret+temp*(las-i+1)+mode)%mode;
}
ret=(1+mode-ret)%mode;
return S[x]=ret;
}
ll get_sum(ll x)
{
ll las=0,ret=0;
for(int i=1;i<=x;i=las+1)
{
las=x/(x/i);
ret+=(las-i+1)*(x/i)%mode;
ret%=mode;
}
return ret*ret%mode;
}
ll solve(ll n)
{
ll las=0,ret=0;
for(int i=1;i<=n;i=las+1)
{
las=n/(n/i);
ret+=(get_S(las)-get_S(i-1)+mode)%mode*get_sum(n/i)%mode;
ret%=mode;
}
return ret;
}
int main()
{
init();
ll n;
scanf("%lld",&n);
printf("%lld\n",solve(n));
return 0;
}

posted @ 2019-07-08 11:54  lleozhang  Views(126)  Comments(0Edit  收藏
levels of contents