[杜教筛] BZOJ4176. Lucas的数论

来源:互联网 发布:2017支付宝和淘宝解绑 编辑:程序博客网 时间:2024/06/05 19:00

陈老师R老师等式

i=1nj=1nf(ij)=i=1nj=1nninj[(i,j)=1]

反演一下就变成

i=1nμ(i)(d=1ninid)2

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

#include <cstdio>#include <iostream>#include <algorithm>#include <map>using namespace std;const int N=10000010,P=1000000007;int p[N],mu[N];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[n];  if(S.count(n)) return S[n];  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[n]=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;}
原创粉丝点击