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 }

 

转载于:https://www.cnblogs.com/AlphaWA/p/10498814.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值