概述
2020ICPC 江西省大学生程序设计竞赛
Problem
Solution
- 首先可以想到逆向思维:
先求出所有情况的和sum,然后减去所有的 g c d ( i , j ) ≠ 1 gcd(i, j) neq 1 gcd(i,j)=1 的情况 - 如何删去
g
c
d
(
i
,
j
)
≠
1
gcd(i, j) neq 1
gcd(i,j)=1 的情况:
可以按照调和级数的方式来考虑
考虑 能被 2 整除的 i ,然后把每个 i 中 能被 2 整除的 j 删掉
考虑 能被 3 整除的 i ,然后把每个 i 中 能被 3 整除的 j 删掉
考虑 能被 5 整除的 i ,然后把每个 i 中 能被 5 整除的 j 删掉
… …
以此类推
但,这样会有重复删掉的,就比如删 i = 6, j = 6时,6 被删了两次
那么,灵感来了,这不就是容斥原理吗?
把多删的加回来,把多加回来的删掉。。。 - 容斥原理如何处理
- 可以考虑莫比乌斯函数,感觉莫比乌斯函数就是为 容斥原理量身定做的。(具体见代码)
- 可以不用上面的思路,换一种解题思路:
- 可以依次考虑每个 i ,求出 i 的所有质因数,然后用容斥原理求出来每个 与 i 互素的 j ,减去这些情况即可。
- 然后分析,该方法的合理性,首先 O ( n n ) O(n sqrt n) O(nn) 预处理出每个数的所有质因数,n只有1e5
- 然后可以发现 2 × 3 × 5 × 7 × 11 × 13 = 30030 2 times 3 times 5 times 7 times 11 times 13 = 30030 2×3×5×7×11×13=30030,就意味着一个数最多有5个质因数
- 处理出所有的 i 的 不互质的 j, 最糟糕时间复杂度 O ( 32 n ) O(32n) O(32n)
- 总的时间复杂度 O ( n n + 32 n ) O(n sqrt n + 32n) O(nn+32n)
Code
const int N = 1e5 + 5;
int a[N], miu[N], v[N];
ll sum[N], f[N];
int solve(int x)
{
int sum = 0;
while (x)
{
sum += x % 10;
x /= 10;
}
return sum;
}
int main()
{
IOS;
int n; cin >> n;
for (int i = 1; i <= n; i++) miu[i] = 1, v[i] = 0;
for (int i = 2; i <= n; i++)//预处理出1 ~ n的莫比乌斯函数值
{
if (v[i]) continue;
miu[i] = -1;
for (int j = i * 2; j <= n; j += i)
{
v[j] = 1;
if (j / i % i == 0) miu[j] = 0;
else miu[j] *= -1;
}
}
for (int i = 1; i <= n; i++)
{
f[i] = solve(i);
sum[i] = f[i] + sum[i - 1];
}
for (int i = 1; i <= n; i++)
sum[i] += sum[i - 1];
ll ans = sum[n];//所有情况的总和
for (int i = 2; i <= n; i++)
{
ll sum = 0, cnt = 0;
for (int j = i; j <= n; j += i)
{
cnt += f[j];
sum += cnt;
}
ans += miu[i] * sum;
}
cout << ans << endl;
return 0;
}
最后
以上就是文静世界为你收集整理的A Simple Math Problem(容斥原理)的全部内容,希望文章能够帮你解决A Simple Math Problem(容斥原理)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复