P5218 无聊的水题 II
题目
求有多少种选数方案使得这些数的 \(\gcd\) 为 \(1\) ,值域 \([1,n]\)。
分析
设 \(f(x)\) 表示选出来的数的 \(\gcd=x\) 的方案数。
那么我们要求的就是 \(f(1)\) ,考虑反演回来求,于是设 \(\large g(x)=\sum\limits_{x\vert d}f(d)\) 。
考虑 \(g\) 的含义,就是表示选出来的数 \(\gcd\) 是 \(x\) 倍数的方案数。
这个很好做,也就是对于 \(x\) 的所有倍数有两种选择:选/不选,其他的数只有一种选择:不选。
再减掉什么都不选的方案,那么这个就是 \(\large g(x)=2^{\lfloor\frac nx\rfloor}-1\) 。
反演回来:
\[\large f(x)=\sum_{x\vert d}\mu(\frac dx)g(d)
\]
再代入 \(x=1\) :
\[\large f(1)=\sum\limits_{d=1}^ng(d)\mu(d)=\sum\limits_{d=1}^n(2^{\lfloor\frac nd\rfloor}-1)\mu(d)
\]
然后需要杜教筛处理 \(\mu\) 的前缀和。
最后数论分块即可。
代码
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
#define ull unsigned long long
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define dep(i,y,x) for(int i=(y);i>=(x);i--)
const int N=1e7+5,M=2e5+5;
const ll V=1e11,t=1e7,MOD=1e9+7;
int prime[N],cnt,mu[N];
ll n,preu[N],Ans,Pow1[N],Pow2[N];
bool isprime[N];
inline ll inc(ll x,ll y){x+=y;return x>=MOD?x-MOD:x;}
inline void incc(ll &x,ll y){x+=y;if(x>=MOD) x-=MOD;}
inline void decc(ll &x,ll y){x-=y;if(x<0) x+=MOD;}
inline ll dec(ll x,ll y){x-=y;return x<0?x+MOD:x;}
bool vis[N];
inline void GetPrimes(int d){
mu[1]=preu[1]=1;
for(int i=2;i<=d;i++){
if(!isprime[i]) prime[++cnt]=i,mu[i]=-1;
preu[i]=preu[i-1]+mu[i];
for(int j=1;j<=cnt&&i*prime[j]<=d;j++){
isprime[i*prime[j]]=true;
if(i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
return ;
}
namespace Map{
const int Size=1e6+5;
int head[Size],nex[Size],idx;
ll to[Size],val[Size];
const int mod=999983;
inline void Insert(ll x,ll v){
int key=(x%mod*131)%mod*13%mod;
for(int i=head[key];i;i=nex[i]) if(to[i]==x) return val[i]+=v,void();
nex[++idx]=head[key],to[idx]=x,val[idx]+=v,head[key]=idx;
return ;
}
inline int Count(ll x){
int key=(x%mod*131)%mod*13%mod;
for(int i=head[key];i;i=nex[i]) if(to[i]==x) return val[i];
return 0;
}
}
unordered_map<ll,ll>preuu;
inline ll Getpremu(ll x){
if(x<=t) return preu[x];
ll k=Map::Count(x);
if(k) return k;
ll res=1;
for(ll l=2,r;l<=x;l=r+1){
r=x/(x/l);
decc(res,(r-l+1)%MOD*Getpremu(x/l)%MOD);
}
return Map::Insert(x,res),res;
}
inline ll QPow(ll x){return Pow1[x%t]*Pow2[x/t]%MOD;}
signed main(){
GetPrimes(t);
read(n);Pow1[0]=Pow2[0]=1;
for(int i=1;i<=t;i++) Pow1[i]=inc(Pow1[i-1],Pow1[i-1]);
for(int i=1;i<=t+1;i++) Pow2[i]=Pow2[i-1]*Pow1[t]%MOD;
for(ll l=1,r;l<=n;l=r+1) r=n/(n/l),incc(Ans,dec(Getpremu(r),Getpremu(l-1))*dec(QPow(n/l),1)%MOD);
write(Ans);
return 0;
}