bzoj2440 - 完全平方數(莫比烏斯函式,容斥原理)
阿新 • • 發佈:2020-11-30
題目
小 X 自幼就很喜歡數。但奇怪的是,他十分討厭完全平方數。他覺得這些
數看起來很令人難受。由此,他也討厭所有是完全平方數的正整數倍的數。然而
這絲毫不影響他對其他數的熱愛。
這天是小X的生日,小 W 想送一個數給他作為生日禮物。當然他不能送一
個小X討厭的數。他列出了所有小X不討厭的數,然後選取了第 K個數送給了
小X。小X很開心地收下了。
然而現在小 W 卻記不起送給小X的是哪個數了。你能幫他一下嗎?
題解
容易想到二分答案,故關鍵在於求區間[1, n]中不含平方因子的數個數,設這個函式為\(f(n)\)。
假設[1, n]中含有質數\(p_1,p_2,...p_k\),由容斥原理可得
因為分母是平方數,我們可以列舉分母的值,列舉複雜度為\(O(\sqrt{n})\)。那麼前面係數怎麼求?容易發現,這個係數就是莫比烏斯函式的值!質因數個數為奇數時減 和 質因數個數為偶數時加 真好對應莫比烏斯函式的\((-1)^k\)
也可以寫成
\[\sum\limits^{n}_{i=1}{\mu(i)^2}=\sum\limits^{i^2\le n}_{i=1}{\mu(i)\lfloor\frac{n}{i^2}\rfloor} \]#include <bits/stdc++.h> #define endl '\n' #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0) #define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout) #define FI freopen(".//data_generator//in.txt","r",stdin) #define FO freopen("res.txt","w",stdout) #define mp make_pair #define seteps(N) fixed << setprecision(N) typedef long long ll; using namespace std; /*-----------------------------------------------------------------*/ ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} #define INF 0x3f3f3f3f const int N = 1e5 + 10; const double eps = 1e-5; int mu[N]; int prime[N]; bool vis[N]; int cnt; void init() { mu[1] = 1; for(int i = 2; i < N; i++) { if(!vis[i]) { prime[cnt++] = i; mu[i] = -1; } for(int j = 0; j < cnt; j++) { int p = prime[j]; if(i * p > N) break; vis[i * p] = 1; if(i % p == 0) { mu[i * p] = 0; break; } mu[i * p] = -mu[i]; } } } ll get(ll n) { ll res = 0; for(int i = 1; 1ll * i * i <= n; i++) { res += mu[i] * (n / (1ll * i * i)); } return res; } int main() { IOS; init(); int t; cin >> t; while(t--) { int k; cin >> k; ll l = 1, r = 1800000000; while(l <= r) { ll mid = (l + r) / 2; if(get(mid) >= k) { r = mid - 1; } else { l = mid + 1; } } cout << l << endl; } }