P4318 Powerful Number 筛做法
这是一篇基于 Powerful Number 筛推导的题解。
Liuhy2996 吃饭的时候口胡出来了,膜拜他/bx。
Powerful Number 筛
定义一个数
不难证明 Powerful Number 的个数是
PN 筛常用于求一个积性函数
容易发现,有性质
其中,
Solution
原问题容易转换为:
构造:
由于只有所有质因子次数为
整出分块一下做完了。不过还可以更优。注意到:
这就做到
#include<bits/stdc++.h>
#define int long long
#define x first
#define y second
using namespace std;
const int N=2e7+10,mod=998244353;
typedef pair<int,int> pii;
typedef long long ll;
/*
*/
int C,T=1,B=5e6;
int n,primes[N],tot,vis[N],mu[N];
int stk[N],ustk[N],sum[N];
void init(int n){
mu[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) primes[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*primes[j]<=n;j++){
vis[i*primes[j]]=1;
if(i%primes[j]==0) break;
mu[i*primes[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
int Solve(int n){
int res=0,val;
for(int l=1,r;l<=n/l;l=r+1)
val=n/(l*l),r=sqrt(n/val),res+=val*(sum[r]-sum[l-1]);
return res;
}
int book[N];
void mian(){
cin>>n;
int l=1,r=1e10,ans=1e10;
while(l<=r){
int mid=(l+r)>>1;
if(Solve(mid)>=n) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<"\n";
return;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>T; init(B);
while(T--) mian();
return 0;
}
顺带物理数学方法证明一下:
由于
然后就做完了。