题意:

有\(m(1 \leq m \leq 10^9)\)个石子排成一圈,编号分别为\(0,1,2 \cdots m-1\)。
现在在\(0\)号石头上有\(n(1 \leq n \leq 10^4)\)只青蛙。第\(i\)只青蛙每次能往前跳\(a_i\)步,但是他们跳的次数不加限制。
如果一块石头能至少被一只青蛙跳上去,那么称这块石头被占领了。
求所有可能被占领的石头的编号和。

分析:

首先我们应该发现这样一个事实:

每次向前跳\(a_i\)步的效果和跳\(GCD(a_i, m)\)步是一样的

所以可以对每个\(a_i\)和\(m\)求个\(GCD\),然后排序去重,这样\(a_i\)的数量就会很少。
在第一个样例中,\(m=12\),求完\(GCD\)的\(a_i\)为\((2, 3)\)。
那么被\(2\)占领的石块的编号为\((0, 2, 4, 6, 8, 10)\);被\(3\)占领的石块的编号为\((0, 3, 6, 9)\)。
显然这样是有重复的,\(6\)号石块既会被\(2\)占领,又会被\(3\)占领。

和HDU 5528 Count a * b这题一样,为了避免算重,我们规定:

编号为\(i\)的石块只会被步长为\(GCD(i, m)\)的青蛙占领

在这之前我们还要预处理一下:
找出\(m\)所有的约数,然后用一个标记数组标记这些约数中存在哪些步长的青蛙。还要把所有步长的倍数也都标记上,也就是说有一个步长为\(d\)的青蛙,如果\(kd\)也是\(m\)的约数,我们可以假设还有一只步长为\(kd\)的青蛙存在。因为这样并不影响最终的结果。

还是上面那个例子,对于步长为\(2\)的青蛙,我们只统计\((2,10)\)这两个石块。其他的\((4,8)\)这两个石块会在步长为\(4\)的青蛙中统计,\((6)\)这个石块会在步长为\(6\)的青蛙中统计上。

一般地,对于步长为\(d\)的青蛙,我们要统计的石块的个数就是\([1,\frac{m}{d}]\)互质的个数,即\(\phi(\frac{m}{d})\)。
这些石块的编号和为\(d \cdot \frac{\frac{m}{d} \phi(\frac{m}{d})}{2}=m\frac{\phi(\frac{m}{d})}{2}\)。

解释一下上面公式
其实我们只需要证明这样一条公式:

\(n > 1\)时,\([1,n]\)中与\(n\)互质的数字之和为:\(\frac{n \phi(n)}{2}\)

证明
因为\(GCD(n,i)=GCD(n,n-i)\),所以如果有\(GCD(n,i)=1\),那么也一定有\(GCD(n,n-i)=1\)成立。
所以满足\(GCD(n,i)=1\)的数都是成对出现的,而且它俩的和为\(n\)。
还要证明一下,这样不会算重,也就是不会出现\(i=n-i\)的情况。
因为如果\(i=n-i \Rightarrow n=2i\),得到\(n\)是偶数,\(i=\frac{n}{2}\)。显然\(GCD(n,i) \neq 1\),推出矛盾。
上面是针对\(n>2\)的情况,幸运的是,\(n=2\)也满足这条公式。
证毕。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define MP make_pair
using namespace std;typedef long long LL;
typedef pair<int, int> PII;
const int maxp = 32000;int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); }int pcnt;
int prime[maxp], phi[maxp];
bool vis[maxp];void preprocess() {for(int i = 2; i < maxp; i++) {if(!vis[i]) {prime[pcnt++] = i;phi[i] = i - 1;}for(int j = 0; j < pcnt && i * prime[j] < maxp; j++) {vis[i * prime[j]] = true;if(i % prime[j] == 0) {phi[i * prime[j]] = phi[i] * prime[j];break;}else phi[i * prime[j]] = phi[i] * (prime[j] - 1);}}
}LL Phi(int n) {if(n < maxp) return phi[n];LL ans = 1;for(int i = 0; i < pcnt; i++) {if(prime[i] * prime[i] > n) break;for(int j = 0; n % prime[i] == 0; j++) {if(!j) ans *= (prime[i] - 1);else ans *= prime[i];n /= prime[i];}}if(n > 1) ans *= (n - 1);return ans;
}const int maxn = 10000 + 10;
int n, m;
int a[maxn];vector<PII> divide;
vector<int> factors;
bool occupied[maxn];void dfs(int d, int x) {if(d == divide.size()) {factors.push_back(x);return ;}int p = divide[d].first, e = divide[d].second;for(int i = 0; i <= e; i++) {dfs(d+1, x);x *= p;}
}int main()
{preprocess();int T; scanf("%d", &T);for(int kase = 1; kase <= T; kase++) {printf("Case #%d: ", kase);scanf("%d%d", &n, &m);for(int i = 0; i < n; i++) {scanf("%d", a + i);a[i] = gcd(m, a[i]);}sort(a, a + n);n = unique(a, a + n) - a;if(a[0] == 1) { printf("%lld\n", (LL)m * (m-1) / 2); continue; }divide.clear();int t = m;for(int i = 0; i < pcnt; i++) {if(prime[i] * prime[i] > t) break;if(t % prime[i] == 0) {int cnt = 0;while(t % prime[i] == 0) {t /= prime[i];cnt++;}divide.push_back(MP(prime[i], cnt));}}if(t > 1) divide.push_back(MP(t, 1));factors.clear();dfs(0, 1);sort(factors.begin(), factors.end());int sz = factors.size();memset(occupied, false, sizeof(occupied));for(int i = 0; i < n; i++) {int k = lower_bound(factors.begin(), factors.end(), a[i]) - factors.begin();occupied[k] = true;}for(int i = 1; i < sz; i++) if(!occupied[i])for(int j = 0; j < i; j++) if(factors[i] % factors[j] == 0 && occupied[j]) {occupied[i] = true;break;}LL ans = 0;for(int i = 0; i < sz - 1; i++) if(occupied[i]) {int t = m / factors[i];ans += (LL)m * Phi(t) / 2;}printf("%lld\n", ans);}return 0;
}

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4939910.html

HDU 5514 Frogs 欧拉函数相关推荐

  1. hdu 4983(欧拉函数)

    题目大意:给出一组n和k,求解满足公式:gcd(n-a,n)*gcd(n-b,n)=n^k的(a,b)的对数,结果对(1e9+7)取模. 先证明:对于1<=x<=n,有gcd(n-x , ...

  2. HDU 2588 GCD(欧拉函数)

    GCD 思路 题目要求,对于给定的n,mn, mn,m要求有多少数∑i=1ngcd(i,n)>=m\sum _{i = 1} ^{n} gcd(i, n) >= m∑i=1n​gcd(i, ...

  3. hdu 1286( 欧拉函数 )

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1286 数学题真的是有点吃不消了... View Code 1 #include<iostream ...

  4. hdu (欧拉函数+容斥原理) GCD

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1695 看了别人的方法才会做 参考博客http://blog.csdn.net/shiren_Bod/ar ...

  5. HDU 1286 找新朋友 (欧拉函数)

    找新朋友 http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=2&sectionid=1&problemid=8 T ...

  6. (hdu step 7.2.1)The Euler function(欧拉函数模板题——求phi[a]到phi[b]的和)

    题目: The Euler function Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...

  7. hdu 1286 找新朋友 欧拉函数模版题

    找新朋友 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Des ...

  8. hdu 3501 欧拉函数

    容易想到容斥原理,但是结合欧拉函数的公式,我们得到: 小于n且与n互质的数的和为:n * phi(n) / 2 于是问题迎刃而解. 1 #include <iostream> 2 #inc ...

  9. hdu 4983 Goffi and GCD(欧拉函数)

    Problem Description Goffi is doing his math homework and he finds an equality on his text book: gcd( ...

最新文章

  1. java 的回调函数
  2. R语言构建文本分类模型并使用LIME进行模型解释实战:文本数据预处理、构建词袋模型、构建xgboost文本分类模型、基于文本训练数据以及模型构建LIME解释器解释多个测试语料的预测结果并可视化
  3. 大连交通大学c语言考试题库,川哥的吩咐 (C语言代码)本着追大连交通大学的故事番,来简单解答一波!!!...
  4. pyqt5动态删除控件问题
  5. good way for university professors accumulating the citation
  6. Linux 高级存储管理
  7. 要多大内存才满足_佛龛的尺寸要多大?
  8. 机器学习速成课程 | 练习 | Google Development——编程练习:特征集
  9. python写spark_python开发sparkSQL应用
  10. CSS类选择器选择多个类用逗号隔开
  11. Spring之@Configuration配置解析
  12. AIR访问操作系统剪贴板粘贴操作延迟呈现解决办法
  13. 正点原子linux使用eclipse,Eclipse+GCC开发环境针对STM32F103ZE的开发模板,完美实现C++编程及JTAG调试...
  14. 插头dp ——从入门到跳楼
  15. PackageManager解析
  16. Ansible的脚本(playbook剧本)
  17. Express Cookie的使用
  18. 张果老能是鸿蒙时期一蝙蝠,历史书中张果老的故事,一只蝙蝠的传奇
  19. JS实现浏览器打印、打印预览
  20. utorrent 连接到用户_用utorrent进行BT下载时如何屏蔽吸血用户的连接

热门文章

  1. python自动化办公第二节_自动化测试第二节-jmeter关联+抓包+python基础
  2. 动态规划|最大k乘积问题(C语言)
  3. 安装cuda 非root_linux非root用户下安装软件,搭建生产环境
  4. 怎么把程序内部坐标转为屏幕坐标_全网最详细CNC加工中心程序代码大全!
  5. go语言变量声明、匿名变量
  6. arouter跨module传递消息_利用ARouter实现组件间通信,解决子模块调用主模块问题...
  7. mybatis java8_Java 8 开发的 Mybatis 注解代码生成工具
  8. 「第一弹」电子设计大赛应该准备什么?
  9. HDLBits答案(6)_硬件模块设计的思考方式
  10. mysql 权限命令 revoke_mysql 权限管理使用 grant/revoke