P5218 无聊的水题 II

题目

求有多少种选数方案使得这些数的 \(\gcd\)\(1\) ,值域 \([1,n]\)

P5218 无聊的水题 II

分析

\(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;
}
posted @ 2021-09-05 11:20  __Anchor  阅读(27)  评论(0编辑  收藏  举报