原题传送门

题意:

有n只青蛙,m块石头呈环放置(从0~m-1标记),第i只青蛙每次跳ai步,跳跃次数无限制。求被n只青蛙踩过的石头的下表和

思路1(欧拉函数):

很明显,对于第i只青蛙,被踩的石头的编号一定是gcd(ai, m)的倍数,那么我们先将ai转换为gcd(ai,m)
然后对于第 j 块石头,我们定义它只能被跳跃步数为x的青蛙踩中(x满足gcd(m,j)= x)例如下面的样例:

2 12
9 10
那么这个样例之中被踩过并且有贡献的石头编号为2,3,4,6,8,9,10
按照我们的定义
2 10 是被跳跃步数为2的青蛙踩过
3 9 是被跳跃步数为3的青蛙踩过
4 8 是被跳跃步数为4的青蛙踩过
6 是被跳跃步数为6的青蛙踩过

这里的青蛙只有两个,但是我们可以造两个步数为4 和 6的青蛙,这对答案是完全没有影响的
因此 x 的答案贡献为 m以内 j [gcd(m,j)== x]
由gcd(m,j)= x,可以得到gcd(m/x,j/x)= 1,即(j/x)为(m/x)内所有与(m/x)互素的数
那么上面对于x的答案贡献就转换为 x * i [gcd(m/x,i)== 1]

知识点:设小于n的所有与n互质的数的和为Sum,Sum=n∗φ(n)/2

证明:
1. gcd(x,n)= 1,那么gcd(n-x,n)= 1同样满足
2. 可见n以内与n互素的数字都是成对出现的,而素数对的个数就是φ(n)/2,并且每一对素数和为n
证毕

由此x的答案再次变换为

x *(φ(m/x)/ 2 *(m/x))

稍稍化简得到

φ(m/x)/ 2*m

到这里就可以直接枚举m的因子,看跳跃步数为当前的因子fac青蛙能否被构造(fac % ai == 0)即可

AC代码1:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e4 + 9;int a[N], fac[N];int Euler (int n) {ll res = n;for (int i = 2; i * i <= n; i++) {if (n % i == 0) {res = res / i * (i - 1);while (n % i == 0) {n /= i;}}}if (n > 1) {res = res / n * (n - 1);}return res;
}int get_fac(int n) {int len = 0;for (int i = 2; i * i <= n; i ++) {if (n % i == 0) {fac[len++] = i;if (i * i != n) {fac[len++] = n / i;}}}sort (fac, fac + len);return len;
}int main() {int T, cnt = 1;scanf ("%d", &T);while (T --) {int n, m;bool flag = false;scanf ("%d%d", &n, &m);int len = get_fac(m);for (int i = 0; i < n; i ++) {scanf ("%d", a + i);a[i] = __gcd(a[i], m);if (a[i] == 1) {flag = true;}}ll ans = 0;for (int i = 0; i < len; i ++) {for (int j = 0; j < n; j ++) {if (fac[i] % a[j] == 0) {ans += 1ll * Euler(m/fac[i]) * m / 2 ;break;}}}printf ("Case #%d: ", cnt ++);if (flag) {cout << 1ll * m * (m - 1) / 2 << endl;} else {cout << ans << endl;}}return 0;
}

思路2(容斥原理):

首先预处理出m的所有因子,每个因子的答案贡献次数初始化为1,然后根据容斥原理去调节后续每个因子的答案贡献次数。例如下面的样例:

2 24
9 10
24的所有因子为 2,3,4,6,8,12

初始化所有因子的答案贡献为1
计算2的答案贡献的时候,2的答案贡献次数为1,因此4,6,8,12的答案贡献次数 -1
计算3的答案贡献的时候,3的答案贡献次数为1,6和12的答案贡献次数-1
计算4的答案贡献的时候,4的答案贡献次数为1,8和12的答案贡献次数-1
(!高潮来了!)
计算6的答案贡献的时候,答案贡献次数为-1,这个时候12的答案贡献次数 -(-1)也就是+1
计算8的答案贡献的时候,答案贡献次数为-1,后续因子没有8的倍数,因此无须调节其他因子的答案贡献次数
计算12的答案贡献的时候,答案贡献次数为-1,与上面同理
(容斥原理真奇妙)

AC代码2:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e4 + 9;int a[N], vis[N], fac[N];int init(int n) {memset (vis, 0, sizeof vis);int len = 0;for (int i = 2; i * i <= n; i ++) {if (n % i == 0) {fac[len++] = i;if (i * i != n) {fac[len++] = n / i;}}}sort (fac, fac + len);return len;
}int main() {int T, cnt = 1;scanf ("%d", &T);while (T --) {int n, m;bool flag = false;scanf ("%d%d", &n, &m);int len = init(m);for (int i = 0; i < n; i ++) {scanf ("%d", a + i);a[i] = __gcd(a[i], m);if (a[i] == 1) {flag = true;}for (int j = 0; j < len; j ++) {if (fac[j] % a[i] == 0) {vis[j] = 1;}}}ll ans = 0;for (int i = 0; i < len; i ++) {ll res = m / fac[i];ans += res * (res - 1) / 2 * fac[i] * vis[i];for (int j = i + 1; j < len; j ++) {if (fac[j] % fac[i] == 0) {vis[j] -= vis[i];}}}printf ("Case #%d: ", cnt ++);if (flag) {cout << 1ll * m * (m - 1) / 2 << endl;} else {cout << ans << endl;}}return 0;
}

(PS.以上的答案贡献计算都是O(1)的)

HDU 5514Frogs相关推荐

  1. HDU——1106排序(istringstream的使用、STLvector练习)

    排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  2. hdu 5438 Ponds 拓扑排序

    Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem ...

  3. HDU 1248 寒冰王座(全然背包:入门题)

    HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid=1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票 ...

  4. hdu 1312 Red and Black 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 第二条深搜,题目并不难,但是做了我好久好久,由于一个细节,让我赌上了一个晚上的时间. 题目大意: ...

  5. HDU 1429 胜利大逃亡(续) (BFS+位压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)  ...

  6. hdu 1272 小希的迷宫

    Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该 ...

  7. HDOJ 1157 HDU 1157 Who's in the Middle ACM 1157 IN HDU

    MiYu原创, 转帖请注明 : 转载自 ______________白白の屋   题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1157 题目描述: ...

  8. 大数加法【HDU 1002】

    大数加法模板 一般的加法只要int类型的两数直接相加即可,大一点的数可以设为long long类型,而超过长整型的数则属于大数问题了,大数加法其实也比较简单,利用数组实现就可以啦: 主要思想如下: ( ...

  9. hdu 2665(主席树查询区间k大值)

    先贴我自己写的代码做模板虽然跟原博主没什么两样.(一开始空间开的4*maxn,交到hdu上一直TLE很奇怪) #include<bits/stdc++.h> using namespace ...

最新文章

  1. PWM通过RC低通滤波器模拟DAC
  2. excel 打开显示安装office自定义项 安装期间出错
  3. 针对《等保2.0》要求的云上最佳实践——网络安全篇
  4. CCS5.5环境下使用clock()函数测试程序段运行时间
  5. 简述MVC思想与PHP如何实现MVC
  6. redis 持久化 + 主从复制+ 集群
  7. 第五节:轻松掌握 vue 实例的生命周期
  8. Dell Inspiron 6400上安装Fedora 5后使声卡义务正常的方法
  9. 【新人c语言强化训练 】 c 语言强化练习2。1 数据对齐[zt]
  10. c语言调试的意义,C语言的调试
  11. 所属学院mid函数计算机学院,EXCEL答案公式==
  12. ubuntu中无法安装vim
  13. mounted钩子函数_解决Vue中mounted钩子函数获取节点高度出错问题
  14. 原创 牛客网产品笔试题刷题打卡——用户研究
  15. IDEA 2020免费下载(附安装教程)
  16. golang 官方依赖管理工具 dep 使用和持续集成
  17. java 矩阵求秩_线性代数精华3——矩阵的初等变换与矩阵的秩
  18. python工具库,toollib太好用了
  19. LeetCode(Array)1313. Decompress Run-Length Encoded List
  20. 多媒体信息发布终端盒的应用和功能

热门文章

  1. 前端——获取手机验证码案例
  2. Linux下使用磁带机的直接备份操作
  3. 曾风靡全球的 Delphi,要日薄西山了?
  4. 原来3DMAX入门应该这样学!
  5. [土狗之路]coursera 与 oj上的递归练习作业-- 单词翻转 角谷猜想
  6. 从源代码分析DbSet如何通过ObjectStateManager管理entity lifecycle的生命周期
  7. xpad如何改变字体主题
  8. 在Exchange Server 2007中限制部分用户只能收发内部邮件 1
  9. 百度音乐全接口 API
  10. 懒惰(Laziness)、急躁(Impatience)和傲慢(Hubris)