[bzoj2440]完全平方数(二分+mobius反演)

解题关键:由容斥原理得,num=1(9,25,49...)+(36,100,225...)数......

这道题用莫比乌斯的正向函数表达式理解较容易

此题让自己理解了只要与倍数相关即可用mobius。

此题还需要注意的一点,是平方数只需要反演质数。貌似是常识

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<iostream>
 7 using namespace std;
 8 typedef long long ll;
 9 ll t,n;
10 inline ll read(){
11     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
12     ll x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
13     if(k=='-')x=0-x;return x;
14 }
15 //莫比乌斯函数线性筛法
16 const int maxn=100000+5;
17 bool vis[maxn];
18 int prime[maxn],mu[maxn];
19 void init_mu(int n){
20     int cnt=0;
21     mu[1]=1;
22     for(int i=2;i<n;i++){
23         if(!vis[i]){
24             prime[cnt++]=i;
25             mu[i]=-1;
26         }
27         for(int j=0;j<cnt&&i*prime[j]<n;j++){
28             vis[i*prime[j]]=1;
29             if(i%prime[j]==0)   {mu[i*prime[j]]=0;break;}
30             else { mu[i*prime[j]]=-mu[i];}
31         }
32     }
33 }
34 
35 bool check(ll x){
36     ll ans=0;
37     for(ll i=1;i*i<=x;i++){
38         ans+=mu[i]*(x/(i*i));
39     }
40     return ans>=n;
41 }
42 
43 ll erfen(ll l,ll r){
44     while(l<r){
45         ll mid=(l+r)>>1;
46         if(check(mid)) r=mid;
47         else l=mid+1;
48     }
49     return r;
50 }
51 int main(){
52     init_mu(100000);
53     t=read();
54     while(t--){
55         n=read();
56         printf("%lld\n",erfen(1, 10000000000));
57     }
58     
59 }

 

posted @ 2017-08-29 00:57  Elpsywk  阅读(211)  评论(0编辑  收藏  举报