1. 程式人生 > >[中山市選2011] 完全平方數

[中山市選2011] 完全平方數

[題目連結]

          https://www.lydsy.com/JudgeOnline/problem.php?id=2440

[演算法]

          首先 , 不妨二分答案mid , 我們需要判斷的是一個形如"[1 , mid]區間中是否有 >= k個不是完全平方數倍數的數“

          考慮容斥 , 顯然  , 答案為 : mid - 有1個質因子的數的倍數個數 + 有兩個質因子的數的倍數個數 - ... + ....

          不難發現 , 每一項的係數為其莫比烏斯函式

          預處理莫比烏斯函式即可

          時間複雜度 : O(NlogN)

[程式碼]

       

#include<bits/stdc++.h>
using namespace std;
#define MAXD 1000010
typedef long long LL;

LL k;
int miu[MAXD];
bool visited[MAXD]; template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if
(c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void preprocess() { for (int i = 1; i < MAXD; i++) { miu[i] = 1; visited[i] = false; } for (int i = 2; i < MAXD; i++) { if (visited[i]) continue; miu[i] = -1; for (int j = 2; 1LL * i * j < MAXD; j++) { visited[i * j] = true; if (j % i == 0) miu[i * j] = 0; else miu[i * j] *= -1; } } } inline LL calc(LL mid) { LL ret = 0; for (int i = 1; 1LL * i * i <= mid; i++) ret += 1LL * miu[i] * (1LL * mid / (1LL * i * i)); return ret; } int main() { int T; read(T); preprocess(); while (T--) { read(k); LL l = 1 , r = (LL)1e10 , ans; while (l <= r) { LL mid = (l + r) >> 1; if (calc(mid) >= k) { ans = mid; r = mid - 1; } else l = mid + 1; } printf("%lld\n" , ans); } return 0; }