您的位置:首页 > 其它

bzoj 4176 Lucas的数论 莫比乌斯反演

2016-11-02 14:53 363 查看
∑ni=1∑nj=1d(i,j)=∑ni=1∑nj=1∑n2k=1[k|ij]

=∑ni=1∑nj=1∑n2k=1[kgcd(i,k)|j]=∑ni=1∑n2k=1⌊n∗gcd(i,k)k⌋

=∑nd=1∑⌊nd⌋i=1∑⌊n2d⌋k=1⌊nk⌋[gcd(i,k)=1]

=∑nd=1∑⌊nd⌋i=1∑nk=1⌊nk⌋[gcd(i,k)=1]

=∑nd=1∑⌊nd⌋i=1∑nk=1⌊nk⌋∑t|i,t|kμ(t)

=∑nt=1μ(t)∑nd=1∑⌊ndt⌋i=1∑⌊nt⌋k=1⌊nkt⌋

=∑nt=1μ(t)∑nd=1⌊ndt⌋∑⌊nt⌋k=1⌊nkt⌋

=∑nt=1μ(t)∑⌊nt⌋d=1⌊ndt⌋∑⌊nt⌋k=1⌊nkt⌋

=∑nt=1μ(t)(∑⌊nt⌋d=1⌊ndt⌋)2

O(n√)枚举nt , 一段区间的mu的和可以用3944的方法求。

(∑⌊nt⌋d=1⌊ndt⌋)2 也 O(nt−−√)求。

复杂度O(n34)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define M 15000000
#define M1 15000010
#define mod 1000000007
bool ip[M1];
int mu[M1],prime[M1/10];
int cnt,n,ans;
map<int,int>ma;
void init()
{
mu[1]=1;
for(int i=2;i<=M;i++)
{
if(!ip[i])prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*prime[j]<=M;j++)
{
ip[i*prime[j]]=1;
if(i%prime[j]==0)break;
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=M;i++)mu[i]+=mu[i-1];
}
int f(int x)
{
if(x<=M)return mu[x];
if(ma.count(x))return ma[x];
int ret=1;
for(int i=2,last;i<=x;i=last+1)
{
last=x/(x/i);
ret-=f(x/i)*(last-i+1);
}
return ma[x]=ret;
}
int cal(int x)
{
int ret=0;
for(int i=1,last;i<=x;i=last+1)
{
last=x/(x/i);
ret=(ret+(ll)(x/i)*(last-i+1)%mod)%mod;
}
return ret;
}
int main()
{
//freopen("tt.in","r",stdin);
init();
scanf("%d",&n);
for(int i=1,last;i<=n;i=last+1)
{
last=n/(n/i);
int t=cal(n/i);
ans=(ans+(ll)(f(last)-f(i-1))*t%mod*t%mod)%mod;
}
printf("%d\n",(ans+mod)%mod);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: