HDU 5514Frogs
原题传送门
题意:
有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相关推荐
- HDU——1106排序(istringstream的使用、STLvector练习)
排序 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...
- hdu 5438 Ponds 拓扑排序
Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem ...
- HDU 1248 寒冰王座(全然背包:入门题)
HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid=1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票 ...
- hdu 1312 Red and Black 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 第二条深搜,题目并不难,但是做了我好久好久,由于一个细节,让我赌上了一个晚上的时间. 题目大意: ...
- HDU 1429 胜利大逃亡(续) (BFS+位压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) ...
- hdu 1272 小希的迷宫
Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该 ...
- HDOJ 1157 HDU 1157 Who's in the Middle ACM 1157 IN HDU
MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1157 题目描述: ...
- 大数加法【HDU 1002】
大数加法模板 一般的加法只要int类型的两数直接相加即可,大一点的数可以设为long long类型,而超过长整型的数则属于大数问题了,大数加法其实也比较简单,利用数组实现就可以啦: 主要思想如下: ( ...
- hdu 2665(主席树查询区间k大值)
先贴我自己写的代码做模板虽然跟原博主没什么两样.(一开始空间开的4*maxn,交到hdu上一直TLE很奇怪) #include<bits/stdc++.h> using namespace ...
最新文章
- PWM通过RC低通滤波器模拟DAC
- excel 打开显示安装office自定义项 安装期间出错
- 针对《等保2.0》要求的云上最佳实践——网络安全篇
- CCS5.5环境下使用clock()函数测试程序段运行时间
- 简述MVC思想与PHP如何实现MVC
- redis 持久化 + 主从复制+ 集群
- 第五节:轻松掌握 vue 实例的生命周期
- Dell Inspiron 6400上安装Fedora 5后使声卡义务正常的方法
- 【新人c语言强化训练 】 c 语言强化练习2。1 数据对齐[zt]
- c语言调试的意义,C语言的调试
- 所属学院mid函数计算机学院,EXCEL答案公式==
- ubuntu中无法安装vim
- mounted钩子函数_解决Vue中mounted钩子函数获取节点高度出错问题
- 原创 牛客网产品笔试题刷题打卡——用户研究
- IDEA 2020免费下载(附安装教程)
- golang 官方依赖管理工具 dep 使用和持续集成
- java 矩阵求秩_线性代数精华3——矩阵的初等变换与矩阵的秩
- python工具库,toollib太好用了
- LeetCode(Array)1313. Decompress Run-Length Encoded List
- 多媒体信息发布终端盒的应用和功能