Frogs - HDU5514

icpc沈阳2015的题目。

容斥原理和数论的应用。

题目大意为给你一个数组 a[i]a[i]a[i](a[i]a[i]a[i] 即为第 iii 只青蛙的步长) 和若干格子编号为 000 到 m−1m - 1m−1,对于任意的正整数 k,ik, ik,i,编号为 k∗a[i]modmk * a[i] \mod mk∗a[i]modm 的格子会被占用,问所有被占用的格子的编号之和。


首先对于一个 a[i]a[i]a[i],显然所有编号为 gcd⁡(a[i],m)\gcd(a[i], m)gcd(a[i],m) 的倍数的格子会被占用,抛弃掉之前的 a[i]a[i]a[i] ,直接将 gcd⁡(a[i],m)\gcd(a[i], m)gcd(a[i],m) 设为新的 a[i]a[i]a[i],这样的话,我们记 a[i]a[i]a[i] 的倍数组成的集合为 AiA_iAi​,那么最终答案为 S(A1∪A2∪⋯∪An)S(A_1 \cup A_2 \cup \dots \cup A_n)S(A1​∪A2​∪⋯∪An​),其中 S(A)S(A)S(A) 为集合 AAA 中所有元素的和。

这个东西显然可以用容斥做,我们记集合 {A1,A2,…,An}\{A_1, A_2, \dots, A_n\}{A1​,A2​,…,An​} 的幂集为 UUU,那么我们可以枚举 UUU 中所有元素,写出来容斥原理的公式:

S(⋃i=1nAi)=∑B∈P(−1)∣B∣−1S(⋂Ai∈BAi)S(\bigcup_{i = 1}^nA_i) = \sum_{B \in P}(-1)^{|B| - 1}S(\bigcap_{A_i \in B}A_i) S(i=1⋃n​Ai​)=B∈P∑​(−1)∣B∣−1S(Ai​∈B⋂​Ai​)

(不得不说容斥原理的公式写成这个样子真的简洁明了又暴力,直接枚举了 2n2^n2n 种集合)

首先需要明确的是,我们使用容斥原理一定是要有一个出发点的,就是对于某一类集合,我们可以快速统计出来这一类集合的答案之和,因为我们不可能花费 O(2n)O(2^n)O(2n) 的时间复杂度去枚举所有 AiA_iAi​ 的交集情况,在集合数繁多的情况下我们只能对这些集合进行分类合并。

对于本题来说,这个分类方法可以很自然地得出。

我们思考若干集合的交,例如 A1∩A3∩A6A_1 \cap A_3 \cap A_6A1​∩A3​∩A6​,那么在这个集合中的元素一定是 a[1],a[3],a[6]a[1], a[3], a[6]a[1],a[3],a[6] 的公倍数,即一定是 lcm(a[1],a[3],a[6])lcm(a[1], a[3], a[6])lcm(a[1],a[3],a[6]) 的倍数,并且 000 到 mmm 内所有 a[1],a[3],a[6]a[1], a[3], a[6]a[1],a[3],a[6] 的公倍数一定在这个集合中。

对于任意一组集合的并皆是如此,并且,我们不难发现,由于 a[i]a[i]a[i] 都是 mmm 的因数,那么若干个 a[i]a[i]a[i] 的最小公倍数也一定是 mmm 的因数。

所以,我们不妨把集合按照最小公倍数分类来进行容斥。

首先,根据上面的结论,我们有:

S(⋂Ai∈BAi)=12lml(ml−1)=12m(ml−1)S(\bigcap_{A_i \in B} A_i) = \frac 12 l\frac ml(\frac ml - 1) = \frac 12m(\frac ml - 1) S(Ai​∈B⋂​Ai​)=21​llm​(lm​−1)=21​m(lm​−1)

其中 lll 为所有 Ai∈BA_i \in BAi​∈B 的 iii 中 a[i]a[i]a[i] 的最小公倍数。

我们不妨设

l=LCM(B)=lcmAi∈Ba[i]l = LCM(B) = {lcm}_{A_i \in B} a[i] l=LCM(B)=lcmAi​∈B​a[i]

那么我们就可以以对集合按照最小公倍数分类的方式重写容斥原理。

S(⋃i=1nAi)=∑l∣m∑B∈P[LCM(B)=l](−1)∣B∣−1S(⋂Ai∈BAi)S(\bigcup_{i = 1}^nA_i) = \sum_{l|m}\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1}S(\bigcap_{A_i \in B}A_i) S(i=1⋃n​Ai​)=l∣m∑​B∈P∑​[LCM(B)=l](−1)∣B∣−1S(Ai​∈B⋂​Ai​)

=∑l∣m∑B∈P[LCM(B)=l](−1)∣B∣−112m(ml−1)= \sum_{l|m}\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1}\frac 12m(\frac ml - 1) =l∣m∑​B∈P∑​[LCM(B)=l](−1)∣B∣−121​m(lm​−1)

=12m∑l∣m(ml−1)∑B∈P[LCM(B)=l](−1)∣B∣−1= \frac 12m\sum_{l|m}(\frac ml - 1)\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1} =21​ml∣m∑​(lm​−1)B∈P∑​[LCM(B)=l](−1)∣B∣−1

接下来,我们只需要考虑如何计算

∑B∈P[LCM(B)=l](−1)∣B∣−1\sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1} B∈P∑​[LCM(B)=l](−1)∣B∣−1

这一坨式子。

这里我们需要用到一个结论,也就是非常出名的莫比乌斯反演公式:

如果有函数 f(n),g(n)f(n), g(n)f(n),g(n) 满足:

g(n)=∑d∣nf(d)g(n) = \sum_{d|n}f(d) g(n)=d∣n∑​f(d)

那么他们同时也满足:

f(n)=∑d∣nμ(nd)g(d)f(n) = \sum_{d|n}\mu(\frac nd)g(d) f(n)=d∣n∑​μ(dn​)g(d)

这是一个非常非常非常有用的结论,他可以允许我们在枚举最大公约数或最小公倍数时去掉最大/最小,改为枚举公约数或者公倍数。这里的 μ\muμ 是莫比乌斯函数,关于莫比乌斯反演在我另一篇博客中有讲解,可以移步去看,不过这里我们只需要知道这个结论就行了。

在这里,我们不妨设

f(l)=∑B∈P[LCM(B)=l](−1)∣B∣−1f(l) = \sum_{B \in P}[LCM(B) = l](-1)^{|B| - 1} f(l)=B∈P∑​[LCM(B)=l](−1)∣B∣−1

那么我们不难发现对于

g(n)=∑d∣nf(d)g(n) = \sum_{d|n}f(d) g(n)=d∣n∑​f(d)

来说,f(n)f(n)f(n) 表示所有最小公倍数为 nnn 的集合 BBB 的 (−1)∣B∣−1(-1)^{|B| - 1}(−1)∣B∣−1 的和,那么 g(n)g(n)g(n) 即表示所有公倍数为 nnn 的集合 BBB 的 (−1)∣B∣−1(-1)^{|B| - 1}(−1)∣B∣−1 的和。

我们通过求出来 g(n)g(n)g(n) 的式子,然后利用莫比乌斯反演的公式来间接求出 f(n)f(n)f(n) 的式子。

g(n)g(n)g(n) 的式子非常好求,我们只需要知道数组 a[i]a[i]a[i] 中为 nnn 的约数的数的个数即可,假设个数为 xxx。

那么这些约数中任意若干个约数组成的集合都满足公约数为 nnn,即

g(n)=∑i=1x(xi)(−1)i−1=1−(1−1)xg(n) = \sum_{i = 1}^x{x \choose i}(-1)^{i - 1} = 1 - (1 - 1)^x g(n)=i=1∑x​(ix​)(−1)i−1=1−(1−1)x

我们可以得到,当数组 a[i]a[i]a[i] 中为 nnn 的约数的个数为 000 时,g(n)=0g(n) = 0g(n)=0,否则 g(n)=1g(n) = 1g(n)=1。

我们把这个式子代入原式:

S(⋃i=1nAi)=12m∑l∣m(ml−1)f(l)S(\bigcup_{i = 1}^nA_i) = \frac 12m\sum_{l|m}(\frac ml - 1)f(l) S(i=1⋃n​Ai​)=21​ml∣m∑​(lm​−1)f(l)

=12m∑l∣m(ml−1)∑d∣lμ(ld)g(d)= \frac 12m\sum_{l|m}(\frac ml - 1)\sum_{d|l}\mu(\frac ld)g(d) =21​ml∣m∑​(lm​−1)d∣l∑​μ(dl​)g(d)

我们不妨交换一下求和顺序,将 g(d)g(d)g(d) 提前,得到

S(⋃i=1nAi)=12m∑d∣mg(d)∑l∣mdμ(l)(mdl−1)S(\bigcup_{i = 1}^nA_i) = \frac 12m\sum_{d|m}g(d)\sum_{l|\frac md}\mu(l)(\frac m{dl} - 1) S(i=1⋃n​Ai​)=21​md∣m∑​g(d)l∣dm​∑​μ(l)(dlm​−1)

我们设

T(n)=∑d∣nμ(d)(nd−1)=∑d∣nμ(d)nd−∑d∣nμ(d)=ϕ(n)−e(n)T(n) = \sum_{d|n}\mu(d)(\frac nd - 1) = \sum_{d|n}\mu(d)\frac nd - \sum_{d|n}\mu(d) = \phi(n) - e(n) T(n)=d∣n∑​μ(d)(dn​−1)=d∣n∑​μ(d)dn​−d∣n∑​μ(d)=ϕ(n)−e(n)

这里的 ϕ(n)\phi(n)ϕ(n) 是欧拉函数,e(n)e(n)e(n) 是单位函数,仅当 n=1n = 1n=1 时 e(n)=1e(n) = 1e(n)=1,否则 e(n)=0e(n) = 0e(n)=0。

如果你不知道什么是欧拉函数或者单位函数,那你就把它当做一个普通积性函数就可以了,我们仍可以通过积性函数的性质用筛法筛出来函数的值。

所以,最终答案为:

S(⋃i=1nAi)=12m∑d∣mg(d)T(nd)S(\bigcup_{i = 1}^nA_i) = \frac 12m\sum_{d|m}g(d)T(\frac nd) S(i=1⋃n​Ai​)=21​md∣m∑​g(d)T(dn​)

=12m∑d∣mg(d)[ϕ(nd)−e(nd)]= \frac 12m\sum_{d|m}g(d)[\phi(\frac nd) - e(\frac nd)] =21​md∣m∑​g(d)[ϕ(dn​)−e(dn​)]

这样,我们就可以先求出来 mmm 的所有约数,然后对于每个约数 ddd,求出来 g(d),ϕ(d)g(d), \phi(d)g(d),ϕ(d) 的值。

时间复杂度为 O(d(m)n)O(d(m)n)O(d(m)n),其中 d(m)d(m)d(m) 为 mmm 的因数个数,这个值很小,最大只有不到 400040004000 个(据说)。

然而最终代码还是跑得很快的,甚至只需要 71ms71ms71ms。

#include <bits/stdc++.h>const int MAXN = 1e5 + 5;int a[MAXN], ddiv[MAXN], g[MAXN], phi[MAXN], n, m, cnt, prime[MAXN], cnt2;int find(int x) {return std::lower_bound(ddiv + 1, ddiv + cnt + 1, x) - ddiv;
}int e(int x) {return x == 1;
}void solve(int T) {scanf("%d%d", &n, &m);cnt = cnt2 = 0;/*memset(g, 0, sizeof(g));memset(phi, 0, sizeof(phi));memset(ddiv, 0, sizeof(ddiv));memset(prime, 0, sizeof(prime));*/for(int i = 1; i <= n; i++) {int x;scanf("%d", &x);a[i] = std::__gcd(x, m);}std::sort(a + 1, a + n + 1);n = std::unique(a + 1, a + n + 1) - a - 1;for(int i = 1; i * i <= m; i++) {if(m % i != 0) continue;int d1 = i, d2 = m / i;ddiv[++cnt] = d1;if(d1 != d2) ddiv[++cnt] = d2;}std::sort(ddiv + 1, ddiv + cnt + 1);phi[1] = 1;for(int i = 2; i <= cnt; i++) {phi[i] = ddiv[i] - 1;for(int j = 1; j <= cnt2; j++) {if(ddiv[i] % prime[j] != 0) continue;int t1 = ddiv[i] / prime[j];if(t1 % prime[j] == 0) phi[i] = phi[find(t1)] * prime[j];else phi[i] = phi[find(t1)] * (prime[j] - 1);}if(phi[i] == ddiv[i] - 1) prime[++cnt2] = ddiv[i];}for(int i = 1; i <= cnt; i++) {g[i] = 0;for(int j = 1; j <= n; j++)if(ddiv[i] % a[j] == 0) {g[i] = 1; break;}}long long ans = 0;for(int i = 1; i <= cnt; i++) ans = ans + 1LL * g[i] * (phi[find(m / ddiv[i])] - (i == cnt));ans = ans * m / 2;printf("Case #%d: %lld\n", T, ans);
}int main() {int T;scanf("%d", &T);for(int i = 1; i <= T; i++) solve(i);return 0;
}

Frogs - HDU5514相关推荐

  1. HDU5514 Frogs

    HDU5514 Frogs 题意:将\([0,m)\)所有符合\(a[i]*t ~mod~ m\)的值求和 做法: \(a[i]*t ~mod~ m\) 会在 \(gcd(a[i],m)\) 的倍数出 ...

  2. HDU-5514 Frogs

    题目大意是给定一些(n)青蛙及其跳跃的步数和方法,给定一些石头,编号从1~m,问所有曾经被青蛙跳过的石头的编号的和. 思路 容斥定理 从题目中很容易得出每一个青蛙的跳过的石头编号是k * gcd(m, ...

  3. Frogs HDU - 5514

    Frogs HDU - 5514 题意: 有n个青蛙,第 i 个青蛙每次只能够跳 ai​步,现在有m个石头围成一圈,编号为0到m−1,现在青蛙可以围着这个石头组成的圆跳无限次,每跳一次就会占领这个石头 ...

  4. POJ 1659 Frogs#39; Neighborhood(度序列组成)

    意甲冠军  中国 依据Havel-Hakimi定理构图即可咯  先把顶点按度数从大到小排序  可图的话  度数大的顶点与它后面的度数个顶点相连肯定是满足的  出现了-1就说明不可图了 #include ...

  5. 【论文笔记】Poison Frogs! Targeted Clean-Label Poisoning Attacks on Neural Networks

    Poison Frogs! Targeted Clean-Label Poisoning Attacks on Neural Networks 引言 创新性 本篇论文的贡献(目的) 算法步骤 实验结果 ...

  6. POJ1659 Frogs' Neighborhood(Havel定理)

    题目: Frogs' Neighborhood Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9932   Accepted ...

  7. hdoj 5514 Frogs

    题目链接:Frogs 题目大意:有一个n个洞的圈,编号从0到m-1,然后有n只青蛙,起始为编号0,每次的步数是k步,问无限的时间后所有可以被青蛙访问的洞的编号 题目思路:我们可以很轻易的想到用gcd( ...

  8. codeforces 609F Frogs and mosquitoes 线段树+二分+multiset

    http://codeforces.com/problemset/problem/609/F There are n frogs sitting on the coordinate axis Ox. ...

  9. HDU 5514 Frogs(欧拉函数+数论YY)

    传送门 Frogs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

最新文章

  1. ios mysql 修改数据,iOS数据库FMDB--增删改查(模糊查询)实写记录
  2. python while循环语句-Python While 循环语句
  3. 转载——C语言中float,double类型,在内存中的结构(存储方式)
  4. 【栈】【856. 括号的分数】【中等】(需回顾)
  5. python怎么解释语言_python是解释型语言吗
  6. c:forEach varStatus属性
  7. C# 4.0 实现 Method Missing
  8. 你真的懂软件测试人员的痛苦吗?——目前软件测试5大误区
  9. mssql 动态行转列。
  10. 高标清上下变换器的测试评估及应用研究
  11. rockchip的pwm驱动框架
  12. Aliddns插件使用:小白超详细图文教程
  13. Mysql中有关Datetime和Timestamp的使用总结
  14. 解决easyui combobox赋值boolean类型的值时,经常出现的内容显示的value而不是text的bug...
  15. SVLAN,CVLAN,PVLAN区别
  16. html5账号秘密,JavaScript有关的10个秘密和怪癖
  17. nexus3的配置阿里云代理仓库
  18. 2022-2027年中国微光器件行业市场调查研究及投资战略研究报告
  19. 红灯停绿灯行c语言编程,基于物联网应用的《C语言程序设计》教学模式研究
  20. hypersion oracle_Oracle收购Hyperion(海波龙)带来的思考与机遇

热门文章

  1. 伦敦银开盘时间知多少
  2. 不在上学了能不能考计算机二级,好多学生都问到底要不要参加计算机二级考试?...
  3. 如何根据PPI网络进一步挖掘信息
  4. 前端接入facebook jsSDK,实现登录授权功能
  5. 【李刚-21天通关Python-03】之 运算符
  6. 搜狐html5,手机搜狐率先发力Html5技术
  7. 微信公众平台流量主单日广告收入最高达5万元 羡煞偶们
  8. 武汉星起航跨境电商到底靠不靠谱?亚马逊跨境收款方式有哪些?
  9. 满屏飞舞的心HTML动画,CSS3制作蝴蝶飞舞动画
  10. UNI-APP之微信小程序转H5