BZOJ2440(容斥+莫比乌斯函数)
题目本质:
首先有如下结论:
而通过写一写可以发现:
举例来讲,36及其倍数的数,会被1的倍数加一遍,被4的倍数扣一遍,会被9的倍数扣一遍,而为了最终计数为0,需要再加回来一遍,所以在容斥里面是正号。
对于36有:6 = 2 * 3,mu[6] = 1;而同时对比16有:4 = 2 * 2,mu[4] = 0;9有:3 = emmm,mu[3] = -1。
枚举到2时,2*2的倍数被扣一遍;枚举到3时,3*3的倍数被扣一遍;枚举到4时,因为它最终只需要扣一遍,而现在已经满足了,所以跳过;枚举到6时,6*6的倍数因为被2和3分别扣过一次,这次要加回来……故可以发现,这个减去还是加上还是不动的选择,刚好与此数的mu值相同。
代码不是主要问题:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <ctime> 7 #include <cctype> 8 #include <climits> 9 #include <iostream> 10 #include <iomanip> 11 #include <algorithm> 12 #include <string> 13 #include <sstream> 14 #include <stack> 15 #include <queue> 16 #include <set> 17 #include <map> 18 #include <vector> 19 #include <list> 20 #include <fstream> 21 #include <bitset> 22 #define init(a, b) memset(a, b, sizeof(a)) 23 #define rep(i, a, b) for (int i = a; i <= b; i++) 24 #define irep(i, a, b) for (int i = a; i >= b; i--) 25 using namespace std; 26 27 typedef double db; 28 typedef long long ll; 29 typedef unsigned long long ull; 30 typedef pair<int, int> P; 31 const int inf = 0x3f3f3f3f; 32 const ll INF = 1e18; 33 34 template <typename T> void read(T &x) { 35 x = 0; 36 int s = 1, c = getchar(); 37 for (; !isdigit(c); c = getchar()) 38 if (c == '-') s = -1; 39 for (; isdigit(c); c = getchar()) 40 x = x * 10 + c - 48; 41 x *= s; 42 } 43 44 template <typename T> void write(T x) { 45 if (x < 0) x = -x, putchar('-'); 46 if (x > 9) write(x / 10); 47 putchar(x % 10 + '0'); 48 } 49 50 template <typename T> void writeln(T x) { 51 write(x); 52 puts(""); 53 } 54 55 const int maxn = 1e5; 56 int mu[maxn], primes[maxn], tot; 57 bool vis[maxn]; 58 59 void pre(int n) { 60 mu[1] = 1; 61 rep(i, 2, n) { 62 if (!vis[i]) { 63 mu[i] = -1; 64 primes[++tot] = i; 65 } 66 for (int j = 1; j <= tot && primes[j] * i <= n; j++) { 67 vis[primes[j] * i] = true; 68 if (i % primes[j] == 0) break; 69 mu[primes[j] * i] = -mu[i]; 70 } 71 } 72 } 73 74 int cal(int x) { 75 int m = sqrt(x), res = 0; 76 rep(i, 1, m) { 77 res += mu[i] * (x / (i * i)); 78 } 79 return res; 80 } 81 82 int solve(int n) { 83 int l = 1, r = 2 * n, ans; 84 while (l <= r) { 85 int mid = (1ll * l + r) >> 1; 86 int k = cal(mid); 87 if (k >= n) ans = mid, r = mid - 1; 88 else l = mid + 1; 89 } 90 return ans; 91 } 92 93 int main() { 94 pre(maxn); 95 int T, n; 96 for (read(T); T; T--) { 97 read(n); 98 writeln(solve(n)); 99 } 100 return 0; 101 }