2440: [中山市選2011]完全平方數
阿新 • • 發佈:2017-11-26
bre 二分枚舉 告訴 esp can pre amp font rim
怎麽感覺一直在做市選的說。。搞得在中山的我都沒信心了。。。
好吧做這題主要是沖著莫比烏斯反演去的,然後實際上也是容斥原理的應用,跟反演沒什麽關系,但是莫比烏斯函數的一個應用。
首先將題目詢問第k個無平方因子數,那麽我立刻想到的是,這些數在莫比烏斯函數中的值是0(但是這個沒什麽用)
實際上的做法是二分枚舉範圍(我覺得這個是神來之筆),然後求這個範圍中有多少個無平方因子數。
那麽個數怎麽求,就是一個容斥原理的應用了:無平方因子數個數=包含0個質數平方的數個數(可能這一項有點難理解,但實際上就是總數)-包含1個質數平方的數個數+包含2個質數質數平方的數個數-包含3個質數平方的數個數……
(PS:具體這個數怎麽求呢,實際上是所以包含x個質數平方因子的數,用總數除以平方就可以得出這個平方出現了多少次了,舉個例子,範圍為40,那包含1個質數平方的數個數是多少呢,就是40/4+40/9+……)
那麽再來回顧一下莫比烏斯函數的定義,含有偶數個不同質數的數 函數值為1,含有奇數個不同質數的數 函數值為-1
發現了什麽?莫比烏斯函數值正好和上面容斥式子的正負是一樣的!舉個例子,4現在我可以輕松的告訴你,ta在容斥式子裏面是減去的,因為ta包含一個質數的乘積,但是我也可以說,因為2的莫比烏斯函數是-1。
那麽具體做法就是枚舉全部的平方數,根據莫比烏斯函數取決他是加還是減。1*1也是平方數啊,n/1*1*u(1)不就是總數咯~
#include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long LL; int pr,prime[210000],u[210000]; bool v[210000]; void mobius_inversion() { pr=0;u[1]=1; memset(v,false,sizeof(v)); for(int i=2;i<=210000;i++) { if(v[i]==false) { u[i]=-1; prime[++pr]=i; } for(int j=1;j<=pr&&i*prime[j]<=210000;j++) { v[i*prime[j]]=true; if(i%prime[j]==0){u[i*prime[j]]=0;break;} u[i*prime[j]]=-u[i]; } } } LL check(LL x) { LL sum=0,t=sqrt(x); for(int i=1;i<=t;i++)sum+=u[i]*x/(i*i); return sum; } int main() { mobius_inversion(); int T; scanf("%d",&T); while(T--) { LL k; scanf("%lld",&k); LL l=k,r=2100000000LL,ans; while(l<=r) { LL mid=(l+r)/2; if(check(mid)>=k) { ans=mid; r=mid-1; } else l=mid+1; } printf("%lld\n",ans); } return 0; }
2440: [中山市選2011]完全平方數