bzoj 2440 完全平方數 【莫比烏斯函式】
阿新 • • 發佈:2019-01-09
題意:第Ki 個不是完全平方數的正整數倍的數。
對於一個數t,t以內的數裡的非完全平方數倍數的個數:num=1的倍數的數量−一個質數平方數(9,25,49...)的倍數的數量+兩個質數的積平方數(36,100,225...)的數量−三個質數balabala……
所以 (然而這一坨是怎麼推出來的呢?)
u(i)就是莫比烏斯函式
求莫比烏斯函式程式碼:
//遞推 ll mu[100005]; void mobius(ll mn) { mu[1]=1; for(ll i=1;i<=mn;i++){ for(ll j=i+i;j<=mn;j+=i){ mu[j]-=mu[i]; } } } //main mobius(100000);
//線性篩法求莫比烏斯函式 bool check[MAXN+10]; int prime[MAXN+10]; int mu[MAXN+10]; void Moblus() { memset(check,false,sizeof(check)); mu[1] = 1; int tot = 0; for(int i = 2; i <= MAXN; i++) { if( !check[i] ){ prime[tot++] = i; mu[i] = -1; } for(int j = 0; j < tot; j++) { if(i * prime[j] > MAXN) break; check[i * prime[j]] = true; if( i % prime[j] == 0){ mu[i * prime[j]] = 0; break; }else{ mu[i * prime[j]] = -mu[i]; } } } }
所以程式碼:
#include <cstdio> #include <cmath> typedef long long ll; const ll M=100001; ll t,n,miu[M],pri[M],bo[M],ans; void makemiu(){ miu[1]=1; for (ll i=2;i<M;i++){ if (!bo[i]){ pri[++pri[0]]=i; miu[i]=-1; } for (ll j=1;j<=pri[0] && pri[j]*i<M;j++){ bo[i*pri[j]]=1; if (i%pri[j]==0){ miu[i*pri[j]]=0; break; }else miu[i*pri[j]]=-miu[i]; } } } ll check(ll t){ ll sq=(int)sqrt(t),res=0; for (ll i=1;i<=sq;i++) res=res+miu[i]*(t/(i*i)); return res; } ll getans(ll t){ ll l=0,r=t*2,mid; while (l+1<r){ mid=(l+r)/2; if (check(mid)<t) l=mid; else r=mid; } return r; } int main(){ scanf("%I64d",&t); makemiu(); for (ll i=1;i<=t;i++){ scanf("%I64d",&n); printf("%I64d\n",getans(n)); } }