容斥原理完全平方数 洛谷P4318
Posted skywalker767
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了容斥原理完全平方数 洛谷P4318相关的知识,希望对你有一定的参考价值。
位卑未敢忘忧国,哪怕无人知我。
一个序列为:不是完全平方数,且不是完全平方数的倍数,该序列从小到大排列,求第k个指是多少。
简单分析下,答案很明显
∑
i
=
1
a
n
s
μ
(
i
)
2
=
k
∑_i = 1 ^ans\\mu(i)^2 = k
i=1∑ansμ(i)2=k
让ans最小就可以了。
考虑杜教筛,T = 50 , 算着杜教筛可行。可惜忘记杜教筛了,改天学了补上。
容斥原理做法:
我们考虑下容斥原理:
我们枚举每一个完全平方数的倍数,利用容斥原理去掉重复的就可以了。
总共有
n
n
n个数。
我们先减去是仅仅一个完全平方数的倍数的个数:即
∑
[
n
i
2
]
∑[\\fracni ^ 2]
∑[i2n]
在加上仅仅是两个完全平方数的倍数的个数。
举个例子:一个的可以为:
2
2
,
3
2
2^2,3^2
22,32,两个的可以为
6
2
6^2
62即:
2
2
×
3
2
2^2\\times3^2
22×32
这个符号是什么呢?是莫比乌斯函数
综上,答案是
∑
i
=
1
i
∗
i
≤
n
μ
(
i
)
[
n
i
2
]
∑_i = 1^i * i \\le n\\mu(i)[\\fracni^2]
i=1∑i∗i≤nμ(i)[i2n]
弄完,二分即可,这个题可以用数论分块加速.
但是笔者在此TLE无数次。
最后经过排查,是二分没开LL
这个就有个问题:为什么数据范围
1
e
9
1e9
1e9,我搞到
2
e
9
2e9
2e9就不行了呢?答案是:下面的l + r >> 1会超int.
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
bool st[N];
int tt , n , primes[N] , cnt , mu[N];
void init(int n)
mu[1] = 1;
for (int i = 2;i <= n;i ++)
if (!st[i]) primes[cnt ++ ] = i , mu[i] = -1;
for (int j = 0;primes[j] <= n / i;j ++)
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
mu[i * primes[j]] -= mu[i];
for (int i = 1;i <= n;i ++) mu[i] += mu[i - 1];
int get(int n , int l)
return n / (n / l);
LL ask(int x)
LL ans = 0;
for (int l = 1 , r;l * l <= x;l = r + 1)
r = min(x , (int)sqrt(get(x , l * l)));
ans += (LL)(mu[r] - mu[l - 1]) * (x / l / l);
return ans;
int main()
init(4e4);
scanf("%d" , &tt);
while (tt -- )
scanf("%d" , &n);
LL l = n , r = n * 2;
while (l < r)
int mid = l + r >> 1;
if (ask(mid) >= n) r = mid;
else l = mid + 1;
printf("%lld\\n" ,l);
return 0;
以上是关于容斥原理完全平方数 洛谷P4318的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ_2440_[中山市选2011]完全平方数_容斥原理+线性筛