描述
小岛: 什么叫做因数分解呢?
doc : 就是将给定的正整数n, 分解为若干个素数连乘的形式.
小岛: 那比如说 n=12 呢?
doc : 那么就是 12 = 2 X 2 X 3 呀.
小岛: 呜呜, 好难, 居然素数会重复出现, 如果分解后每一个素数都只出现一次, 我就会.
wish: 这样来说, 小岛可以正确分解的数字不多呀.
doc : 是呀是呀.
wish: 现在问题来了, 对于给定的k, 第 k 个小岛无法正确分解的数字是多少?
格式
输入格式
输入只有一行, 只有一个整数 k.
输出格式
输出只有一行, 只有一个整数, 表示小岛无法正确分解出来的第k个数字.
样例1
样例输入1
10
样例输出1
27
限制
对于30%的数据, k <= 2,000,000
对于100%的数据, 1 <= k <= 10,000,000,000
提示
前 10 个小岛无法正确分解出来的数字依次是: 4 8 9 12 16 18 20 24 25 27
莫比乌斯反演
小于x的可以正确分解的数字个数是 Σmu[i]*(x/i^2),算不能分解正确的只要把mu反一下就行
AC记录喜+1
注意:此代码目前只过了样例,还没有提交测评,不具有可信度。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int mxn=300010; 8 int pri[mxn]; 9 int mu[mxn]; 10 bool mark[mxn]; 11 int cnt=0; 12 long long k; 13 void getmu(){ 14 int i,j; 15 mu[1]=1; 16 for(i=2;i<=mxn;i++){ 17 if(!mark[i]) pri[++cnt]=i,mu[i]=1; 18 for(j=1;j<=cnt && pri[j]*i<mxn;j++){ 19 mark[pri[j]*i]=1; 20 if(i%pri[j]==0){ 21 mu[i*pri[j]]=0; 22 break; 23 } 24 else mu[i*pri[j]]=-mu[i]; 25 } 26 } 27 return; 28 } 29 int calc(int x){ 30 long long ans=0,m; 31 m=sqrt(x); 32 for(long long i=2;i<=m;i++){ 33 ans+=x/(i*i)*mu[i]; 34 } 35 return ans; 36 } 37 int main(){ 38 long long ans; 39 getmu(); 40 scanf("%d",&k); 41 long long l=k,r=1e10; 42 while(l<=r){ 43 int mid=(l+r)>>1; 44 if(calc(mid)>=k)ans=mid,r=mid-1; 45 else l=mid+1; 46 } 47 printf("%d\n",ans); 48 return 0; 49 }
时间: 2024-10-13 08:35:53