您的位置:首页 > 其它

[杜教筛] BZOJ4176. Lucas的数论

2017-12-21 13:18 411 查看
陈老师R老师等式

∑i=1n∑j=1nf(ij)=∑i=1n∑j=1n⌊ni⌋⌊nj⌋[(i,j)=1]

反演一下就变成

∑i=1nμ(i)(∑d=1⌊ni⌋⌊nid⌋)2

后面的东西也分块求,复杂度证明跟杜教筛复杂度证明差不多

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

const int N=10000010,P=1000000007;

int p
,mu
;

map<int,int> S;

inline int g(int n){
int ret=0;
for(int i=1,j;i<=n;i=j+1){
j=n/(n/i);
ret=(ret+1LL*(j-i+1)*(n/i))%P;
}
return 1LL*ret*ret%P;
}

int Sum(int n){
if(n<=1000000) return mu
;
if(S.count(n)) return S
;
int ret=1;
for(int i=2,j;i<=n;i=j+1){
j=n/(n/i);
ret=(ret-1LL*(j-i+1)*Sum(n/i))%P;
}
return S
=ret;
}

int n;

inline void Pre(){
mu[1]=1;
for(int i=2;i<=1000000 && i<=n;i++){
if(!p[i]) p[++*p]=i,mu[i]=-1;
for(int j=1;j<=*p && 1LL*i*p[j]<=1000000 && 1LL*i*p[j]<=n;j++){
p[i*p[j]]=1;
if(i%p[j]) mu[i*p[j]]=-mu[i];
else break;
}
}
for(int i=1;i<=1000000 && i<=n;i++)
mu[i]=(mu[i]+mu[i-1])%P;
}

int main(){
int ans=0; scanf("%d",&n); Pre();
for(int i=1,j,lst=0;i<=n;i=j+1){
j=n/(n/i); int cur=Sum(j);
ans=(ans+1LL*(cur-lst)*g(n/i))%P;
lst=cur;
}
printf("%d\n",(ans+P)%P);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: