杜教筛学习笔记
主要过程如下:
然后提出含
然后递归求解+记忆化即可(吉大好像有个递推求解的方法,感兴趣的可以去看看),时间复杂度
看看例题吧。
杜教筛模板
于是有:
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define ll long long
const int N=6e6+10,M=6e6;
int t,prime[N],mu[N],n,tot;
ll phi[N];
gp_hash_table<ll,ll>ph,m;
bool vis[N];
inline void init(){
mu[1]=phi[1]=1;vis[1]=1;
for(int i=1;i<=M;i++){
if(!vis[i]){
prime[++tot]=i;
mu[i]=-1;
phi[i]=i-1;
}
for(int j=1;j<=tot&&i*prime[j]<=M;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
mu[i*prime[j]]=-mu[i];
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
for(int i=1;i<=M;i++){
mu[i]+=mu[i-1];
phi[i]+=phi[i-1];
}
}
inline ll s(ll x){
if(x<=M)return mu[x];
if(m[x])return m[x];
ll ans=1;
ll r=yhl;
for(ll l=2;l<=x;l=r+1){
r=x/(x/l);
ans-=(r-l+1)*s(x/l);
}
return m[x]=ans;
}
inline ll sl(ll x){
if(x<=M)return phi[x];
if(ph[x])return ph[x];
ll ans=x*(x+1)>>1;
ll r=yhl;
for(ll l=2;l<=x;l=r+1){
r=x/(x/l);
ans-=(r-l+1)*sl(x/l);
}
return ph[x]=ans;
}
signed main(){
init();
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%lld %lld\n",sl(n),s(n));
}
return yhl;
}
神犇和蒟蒻
那么:
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6,p=1e9+7;
int prime[N],tot,ph[N+10],n,inv;
bool vis[N+10];
unordered_map<int,int>f;
int qum(int a,int b){
int ans=1;
while(b){
(b&1)&&(ans=ans*a%p);
a=a*a%p;
b>>=1;
}
return ans;
}
void init(){
ph[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
prime[++tot]=i;
ph[i]=i-1;
}
for(int j=1;j<=tot&&i*prime[j]<=N;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])){
ph[i*prime[j]]=ph[i]*prime[j]%p;
break;
}
ph[i*prime[j]]=ph[i]*ph[prime[j]]%p;
}
}
for(int i=1;i<=N;i++)ph[i]=ph[i]*i%p;
for(int i=1;i<=N;i++)ph[i]=(ph[i]+ph[i-1])%p;
}
inline int op(int x){
return x*(x+1)%p*(2*x%p+1)%p*inv%p;
}
inline int up(int x){
return x*(x+1)/2%p;
}
int get(int n){
if(n<=N)return ph[n];
if(f[n])return f[n];
int ans=op(n);
for(int l=2,r=0;l<=n;l=r+1){
r=n/(n/l);
ans=(ans-(up(r)-up(l-1)+p)*get(n/l)%p+p)%p;
}
return f[n]=ans;
}
signed main(){
init();inv=qum(6,p-2);
scanf("%lld",&n);
printf("1\n%lld",get(n));
return yhl;
}
简单的数学题
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e6;
int phi[N+10],prime[N+10],tot,n,p,inv,iv;
bool vis[N+10];
unordered_map<int,int>f;
void init(){
phi[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
prime[++tot]=i;
phi[i]=i-1;
}
for(int j=1;j<=tot&&i*prime[j]<=N;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])){phi[i*prime[j]]=phi[i]*prime[j]%p;break;}
phi[i*prime[j]]=phi[i]*phi[prime[j]]%p;
}
}
for(int i=1;i<=N;i++)phi[i]=i*i%p*phi[i]%p;
for(int i=1;i<=N;i++)phi[i]=(phi[i]+phi[i-1])%p;
}
inline int qum(int a,int b){
int ans=1;
while(b){
(b&1)&&(ans=ans*a%p);
a=a*a%p;
b>>=1;
}
return ans;
}
inline int op(int x){
x%=p;
return x*(x+1)%p*iv%p;
}
inline int func(int x){
x%=p;
return x*(x+1)%p*(2*x%p+1)%p*inv%p;
}
int get(int x){
if(x<=N)return phi[x];
if(f[x])return f[x];
int r=op(x);
int ans=(r*r)%p;
for(int i=2;i<=x;i=r+1){
r=x/(x/i);
ans=(ans-(func(r)-func(i-1)+p)%p*get(x/i)%p+p)%p;
}
return f[x]=ans;
}
signed main(){
scanf("%lld%lld",&p,&n);
init();inv=qum(6,p-2);iv=qum(2,p-2);
int ans=yhl;
for(int i=1,r=yhl;i<=n;i=r+1){
r=n/(n/i);
ans=(ans+(get(r)-get(i-1)+p)%p*op(n/i)%p*op(n/i)%p+p)%p;
}
printf("%lld",ans);
return yhl;
}
[bzoj4176] Lucas的数论
有一个这道题的弱化版本,就挂那道题的链接吧
推导过程我在莫反做题记里面写了,这里就不赘述了,自己去看即可(就是太懒不想写柿子了)。
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6,p=1e9+7;
int mu[N+10],ans,n,prime[N],tot;
bool vis[N+10];
unordered_map<int,int>f;
void init(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(int j=1;j<=tot&&i*prime[j]<=N;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j]))break;
mu[i*prime[j]]=mu[i]*mu[prime[j]];
}
}
for(int i=1;i<=N;i++)mu[i]=(mu[i]+mu[i-1]+p)%p;
}
int get_f(int n){
int ans=yhl;
for(int i=1,r;i<=n;i=r+1){
r=n/(n/i);
ans=(ans+(r-i+1)*(n/i)%p)%p;
}
return ans*ans%p;
}
int get_mu(int x){
if(x<=N)return mu[x];
if(f[x])return f[x];
int ans=1;
for(int i=2,r;i<=x;i=r+1){
r=x/(x/i);
ans=(ans-(r-i+1)*get_mu(x/i)%p+p)%p;
}
return f[x]=ans;
}
signed main(){
init();
scanf("%lld",&n);
for(int i=1,r;i<=n;i=r+1){
r=n/(n/i);
ans=(ans+(get_mu(r)-get_mu(i-1)+p)*get_f(n/i)%p)%p;
}
printf("%lld",ans);
return yhl;
}
DZY Loves Math IV
题意
对于给定的
先尝试化简一下:
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6,p=1e9+7;
int phi[N+1],prime[N+1],tot,t[N];
bool vis[N+1];
unordered_map<int,int>ph;
unordered_map<int,int>f[N];
void init(){
phi[1]=t[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
prime[++tot]=i;
phi[i]=i-1;
t[i]=i;
}
for(int j=1;j<=tot&&i*prime[j]<=N;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])){
phi[i*prime[j]]=phi[i]*prime[j]%p;
t[i*prime[j]]=t[i];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]]%p;
t[i*prime[j]]=t[i]*prime[j];
}
}
for(int i=1;i<=N;i++){
phi[i]=(phi[i]+phi[i-1])%p;
}
}
int get_phi(int x){
if(x<=N)return phi[x];
if(ph[x])return ph[x];
int ans=x*(x+1)/2%p;;
for(int i=2,r;i<=x;i=r+1){
r=x/(x/i);
ans=(ans-(r-i+1)*get_phi(x/i)%p+p)%p;
}
return ph[x]=ans;
}
int get_s(int n,int m){
if(n==1)return f[n][m]=get_phi(m);
if(m==1)return (phi[n]-phi[n-1]+p)%p;
if(!m)return yhl;
if(f[n][m])return f[n][m];
int ans=yhl,op=n/t[n];
for(int i=1;i*i<=t[n];i++){
if(!(t[n]%i)){
ans=(ans+(phi[t[n]/i]-phi[t[n]/i-1]+p)*get_s(i,m/i)%p)%p;
if(i*i!=t[n]){
ans=(ans+(phi[i]-phi[i-1]+p)*get_s(t[n]/i,m/(t[n]/i))%p)%p;
}
}
}
return f[n][m]=ans*op%p;
}
signed main(){
init();int n,m;
scanf("%lld%lld",&n,&m);
int ans=yhl;
for(int i=1;i<=n;i++){
ans=(ans+get_s(i,m))%p;
}
printf("%lld",ans);
return yhl;
}
[CQOI2015]选数
题面
即:
点击查看代码
#define yhl 0
#include<bits/stdc++.h?
using namespace std;
#define int long long
const int N=1e6,p=1e9+7;
int prime[N],mu[N+10],tot,l,h,k,ans,n;
unordered_map<int,int> f;
bool vis[N+10];
inline int qum(int a,int b){
int ans=1;
while(b){
(b&1)&&(ans=ans*a%p);
a=a*a%p;
b>>=1;
}
return ans;
}
inline void init(){
vis[1]=mu[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(int j=1;j<=tot&&i*prime[j]<=N;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j]))break;
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=N;i++)mu[i]=(mu[i-1]+mu[i]+p)%p;
}
inline int func(int x){
if(x<=N)return mu[x];
if(f[x])return f[x];
int ans=1;
for(int i=2,r;i<=x;i=r+1){
r=x/(x/i);
ans=(ans-(r-i+1)*func(x/i)%p+p)%p;
}
return f[x]=ans;
}
signed main(){
scanf("%lld%lld%lld%lld",&n,&k,&l,&h);
init();
l=(l-1)/k,h=h/k;
for(int i=1,r;i<=h;i=r+1){
if(l/i)r=min(h/(h/i),l/(l/i));
else r=h/(h/i);
ans=(ans+(func(r)-func(i-1)+p)*qum(h/i-l/i,n)%p)%p;
}
printf("%lld",ans);
return yhl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?