min25筛
被迫营业。
应用范围:求
需要满足
时间复杂度:
主要想法是将
先求出
为了方便起见,我们将
考虑埃氏筛的过程,设
设
否则我们会筛掉一些数,由于是完全积性函数,容易得出转移:
注意
我们考虑计算答案,设
现在这个
设
然后暴力递归求出
求
#define int long long
#define id(x) ((x<=lim)?(id1[x]):(id2[n/(x)]))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
int const N=1e6+10;
int lim,prime[N],w[N],g[N],id1[N],id2[N],m;bool vis[N];
inline void init(){
//预处理根号以内质数
rep(i,2,lim){
if (!vis[i]) prime[++prime[0]]=i;
for (int j=1;j<=prime[0] && i*prime[j]<=lim;++j){
vis[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
inline void solve(){
int n;cin>>n,lim=sqrtl(n),init();
for (int l=1,r;l<=n;l=r+1){
r=n/(n/l),w[++m]=n/l,g[m]=w[m]-1;
if (w[m]<=lim) id1[w[m]]=m;
else id2[n/w[m]]=m;
//预处理 g 数组第一维有可能的取值
}
rep(i,1,prime[0])
for (int j=1;j<=m && prime[i]*prime[i]<=w[j];++j)
g[j]-=g[id(w[j]/prime[i])]-(i-1);
cout<<g[id(n)]<<'\n';
}
#define int long long
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define id(x) ((x<=lim)?(id1[x]):(id2[n/(x)]))
#define add(x,y) (x=((x+y>=mod)?(x+y-mod):(x+y)))
//例:求 f(p^k)=p^k(p^k-1) 的前缀和
//发现 f(p^k)=p^{2k}-p^k
int const mod=1e9+7;
int n;
inline int f(int op,int x){
x%=mod;
if (!op) return x;
return x*x%mod;
}
inline int F(int x){
x%=mod;
return x*(x-1)%mod;
}
inline int smf(int op,int x){
x%=mod;
if (!op) return (x*(x+1)/2)%mod;
return x*(x+1)%mod*(2*x%mod+1)%mod*166666668%mod;
}
//smf -> f 前缀和
int const N=1e6+10;
int lim,prime[N],sp1[N],sp2[N],w[N],g1[N],g2[N],id1[N],id2[N],m;bool vis[N];
inline void init(){
//预处理根号以内质数
rep(i,2,lim){
if (!vis[i]) prime[++prime[0]]=i;
for (int j=1;j<=prime[0] && i*prime[j]<=lim;++j){
vis[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
rep(i,1,prime[0]){
sp1[i]=sp1[i-1],add(sp1[i],f(0,prime[i]));
sp2[i]=sp2[i-1],add(sp2[i],f(1,prime[i]));
}
}
inline int S(int x,int y){
if (prime[y]>=x) return 0;
int ans=((g2[id(x)]+mod-g1[id(x)])%mod+mod-(sp2[y]-sp1[y]+mod)%mod)%mod;
for (int i=y+1;i<=prime[0] && prime[i]*prime[i]<=x;++i)
for (int e=1,gg=prime[i];gg<=x;++e,gg*=prime[i])
add(ans,F(gg)*(S(x/gg,i)+(e>1))%mod);
return ans;
}
inline void solve(){
cin>>n,lim=sqrtl(n),init();
for (int l=1,r;l<=n;l=r+1){
r=n/(n/l),w[++m]=n/l;
g1[m]=(smf(0,w[m])+mod-1)%mod;
g2[m]=(smf(1,w[m])+mod-1)%mod;
if (w[m]<=lim) id1[w[m]]=m;
else id2[n/w[m]]=m;
//预处理 g 数组第一维有可能的取值
}
rep(i,1,prime[0])
for (int j=1;j<=m && prime[i]*prime[i]<=w[j];++j)
add(g1[j],mod-f(0,prime[i])*(g1[id(w[j]/prime[i])]+mod-sp1[i-1])%mod),
add(g2[j],mod-f(1,prime[i])*(g2[id(w[j]/prime[i])]+mod-sp2[i-1])%mod);
cout<<(S(n,0)+1)%mod<<'\n';
}
本文作者:Tx_Lcy
本文链接:https://www.cnblogs.com/tx-lcy/p/18490300
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步