洲阁筛
来源:互联网 发布:mac安装windows很难用 编辑:程序博客网 时间:2024/06/08 10:35
定义非完全积性函数F(x)
我们现在要做的事情是求:
还要满足的是:
考虑将每个x的质因数分成小于等于
注意到当
和
先解决前面的部分:
设
那么有转移:
考虑
就是说,每次处理
由于n以内的质数密度是
所以复杂度是这样分析的:
分子的部分为:
和
所以这部分的时间复杂度是
接着考虑处理后面的部分,回顾一下:
设
那么有转移:
对于
然后就类似前面计算g,一样做就好了
这部分的复杂度跟前面类似
撒花
代码:
待填坑
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<set>#include<bitset>#include<map>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long LL;typedef double db;const int N = 200010;const int L = 16000000;const int mo = 1e+9+7;const int K = 1;int st[N],id[N],s;LL pri[K+1][N],pre[K+1][N];int k;bool bz[N];LL val[N];LL g[K+1][L],f[L],gs[K+1];int tr[L];LL n,qt;LL a[K+1],F[N];int m;map<LL,int>mp;int lim[N];LL add(LL x,LL y){ return x+y>=mo?x+y-mo:x+y;}LL del(LL x,LL y){ return x>=y?x-y:x+mo-y;}void prepare(){ for(LL i=1;i<=n;i=n/(n/i)+1)val[++m]=n/i; qt=sqrt(n); F[1]=1; fo(i,2,qt){ if (!F[i]){ pri[1][++k]=i; F[i]=i-1; } fo(j,1,k){ if (i*pri[1][j]>qt)break; if (i%pri[1][j]==0){ F[i*pri[1][j]]=F[i]*pri[1][j]%mo; break; } F[i*pri[1][j]]=F[i]*(pri[1][j]-1)%mo; } } fo(i,1,m/2)swap(val[i],val[m-i+1]); fo(i,1,k){ LL cnt=1; fo(j,0,K){ pri[j][i]=cnt; pre[j][i]=add(pre[j][i-1],cnt); cnt=cnt*pri[1][i]%mo; } } s=0; fo(i,1,m){ lim[i]=lim[i-1]; while(lim[i]<k&&pri[1][lim[i]+1]<=val[i])lim[i]++; mp[val[i]]=i; st[i]=s+1; id[i]=k; fo(j,1,k) if (1ll*pri[1][j]*pri[1][j]>val[i]){id[i]=j-1;break;} s+=id[i]+1; tr[st[i]]=i; fo(j,1,id[i])tr[st[i]+j]=mp[val[i]/pri[1][j]]; } //---------------------- a[0]=mo-1; a[1]=1;}LL getf(int i,int j){ if (j>lim[i])return 1; if (j>id[i])return (((pre[1][lim[i]]+mo-pre[1][j-1])%mo+mo-(lim[i]-j+1))%mo+1)%mo; return f[st[i]+j];}LL solve(){ //calc g fo(i,1,m){ //---------------- g[0][st[i]]=val[i]%mo; if (val[i]%2)g[1][st[i]]=(val[i]+1)/2%mo*(val[i]%mo)%mo; else g[1][st[i]]=val[i]/2%mo*(val[i]%mo+1)%mo; int u=i; fo(j,1,id[i]){ while(val[u]>val[i]/pri[1][j])u--; if (j-1<=id[u]) fo(x,0,K) g[x][st[i]+j]=del(g[x][st[i]+j-1],pri[x][j]*g[x][st[u]+j-1]); else fo(x,0,K) g[x][st[i]+j]=del(g[x][st[i]+j-1],pri[x][j]*(del(g[x][st[u]+id[u]],del(pre[x][j-1],pre[x][id[u]])))); } } int u=m; LL ans=0; fo(i,1,qt){ while(val[u]>n/i)u--; fo(x,0,K){ LL tmp=del(g[x][st[u]+id[u]],add(del(pre[x][k],pre[x][id[u]]),1)); ans=(ans+(tmp*a[x]%mo)*F[i]%mo)%mo; } //ans=add(ans,F[i]); } fo(i,1,m){ LL cnt=del(del(pre[1][lim[i]],pre[1][id[i]]),(lim[i]-id[i]))+1; fd(j,id[i],1){ LL x=val[i]; LL tmp=pri[1][j]-1; if (j==id[i])f[st[i]+j]=cnt; else f[st[i]+j]=f[st[i]+j+1]; for(int now=i;x>=pri[1][j];){ if (x>=pri[1][j]*pri[1][j]){ now=tr[st[now]+j]; f[st[i]+j]=add(f[st[i]+j],tmp*getf(now,j+1)%mo); } else f[st[i]+j]=add(f[st[i]+j],tmp); x=x/pri[1][j]; tmp=tmp*pri[1][j]%mo; } } } ans=add(ans,f[st[m]+1]); return ans;}int main(){ freopen("data.in","r",stdin); scanf("%lld",&n); prepare(); LL ans=solve(); printf("%lld\n",ans); return 0;}
不知道为什么跑不过10^10….要找张贡提升一下知识水平啦2333
阅读全文
1 0
- 洲阁筛
- 洲阁筛法学习小计
- 洲阁筛学习总结
- Oracle CDC(Change Data Capture)概述
- 视觉目标检测和识别之过去,现在及可能
- Logistic Regression分类器,这个讲解的比较清晰
- PHP使用FPDF的多字体解决
- JS中函数执行顺序的问题
- 洲阁筛
- 组织代码证js验证
- 使用Spring的注解实现Hibernate事务管理
- thinkPHP学习心得 ---架构
- android中常用控件继承关系
- 全志A33N切换分支.repo/repo/repo forall -c "git checkout exdroid-7.1.1_r23-a33-v7.0rc2.1"
- python机器学习day'5
- oracle对三个列求sum
- HDFS——数据备份与放置策略(转)