题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5514

题意 :

有m个石子围成一圈, 有n只青蛙从跳石子, 都从0号石子开始, 每只能越过a[i]个石子

问所有被至少踩过一次的石子的序号之和

思路 :

不难发现, 从0开始, 每次越过a[i]个石子, 那么gcd(a[i], m)的倍数都能被经过

石子 k * (gcd(a[i], m)) < m 的都被算入

但如果按单独每个a[i]来计算对答案的贡献, 肯定会有重复, 重复部分就是lcm(a[i], a[j])的倍数

这里要用容斥的思想解决

第一次正式接触容斥, 但其实已经有很多地方用过这种思想了

比如二维树状数组求面积, 求一个范围内能整除若干个数的个数, 还有某些概率计算

这道题中, 考虑每个gcd(a[i], m)的贡献时

首先 x = gcd(a[i], m) 一定是m的因子, x的贡献是 (m / x) * (m / x - 1) * / 2 * x

因为Sum(k * x) (1 <= k < m / x), 提取x为公因子, k就是一个等差数列求和

此时若有 y = gcd(a[j], m), y % x == 0, 则要减去一次y产生的贡献

所以解法是, 先用处理出所有m的因子, 储存在一个数组d中

对每个a[i], 都算出x = gcd(a[i], m), 遍历m的因子,

若d[i] % m == 0, 就将这个因子的贡献标记为1, vis[i] = 1, 表示这个因子应该做贡献

用一个数组记录每个因子做过的贡献, 一开始全为0

再遍历m的因子, 如果当前这个因子应该做的贡献和已经做的贡献不等, 补上贡献的次数是vis[i] - num[i]

所以套用计算贡献的公式, 当前因子x做的贡献为(m / x) * (m / x - 1) * / 2 * x * (vis[i] - num[i])

这时就要用容斥了, 这些因子中, 如果有y能整除x, x进行贡献的同时, 因子y也同时被贡献了vis[i] - num[i]次

那么对应因子y的num[j]就要加上vis[i] - num[i]

如果出现了vis[i] - num[i] < 0的情况, 说明这个因子被多贡献了, 减去相应次数的贡献即可

重现没有做出来, 代码是参考了网上大牛的

#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;typedef long long LL;const int MAXN = 1e4+10;int a[MAXN];
int d[MAXN];
int vis[MAXN];
int num[MAXN];int GCD(int a, int b)
{int r = a % b;while(r) {a = b;b = r;r = a % b;}return b;
}bool cmp(int a, int b)
{return a < b;
}void Init()
{memset(vis, 0, sizeof(vis));memset(num, 0, sizeof(num));
}int main()
{int t;int n, m;scanf("%d", &t);for(int cas = 1; cas <= t; cas++) {Init();scanf("%d %d", &n, &m);int cnt = 0;for(int i = 1; i * i <= m; i++) {if(m % i == 0) {d[cnt++] = i;if(i * i != m) {d[cnt++] = m / i;}}}sort(d, d+cnt, cmp);for(int i = 0; i < n; i++) {scanf("%d", &a[i]);a[i] = GCD(a[i], m);for(int j = 0; j < cnt; j++) {if(d[j] % a[i] == 0) {vis[j] = 1;}}}LL ans = 0;vis[cnt-1] = 0;for(int i = 0; i < cnt; i++) {if(vis[i] != num[i]) {LL temp = m / d[i];ans += temp * (temp - 1) / 2 * d[i] * (vis[i] - num[i]);for(int j = i + 1; j < cnt; j++) {if(d[j] % d[i] == 0) {num[j] += vis[i] - num[i];}}}}printf("Case #%d: %I64d\n", cas, ans);}return 0;
}

View Code

转载于:https://www.cnblogs.com/Quinte/p/4932471.html

HDU 5514 Frogs (容斥原理)相关推荐

  1. HDU 5514 Frogs (容斥原理+因子分解)

    题目链接 题意:有n只青蛙,m个石头(围成圆圈).第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过的石头的下标总和是多少? 题解:暴力肯定会超时,首先分解出m的因子,自己本身不用分,因为石头编号是0 ...

  2. HDU - 5514 Frogs(容斥原理)

    题目链接:点击查看 题目大意:给出 0 ~ m - 1 共 m 个石头首尾相连呈现出一个环状,初始时在第 0 个石头上有 n 只青蛙,n 只青蛙相互独立,每一只青蛙每次都会向前跳 a[ i ] 步,问 ...

  3. HDU 5514 Frogs

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5514 题目描述: 有n只青蛙,m个石头(围成圆圈).第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过 ...

  4. HDU 5514 Frogs 容斥

    http://acm.hdu.edu.cn/showproblem.php?pid=5514 没有想到怎么利用gcd的性质来改进指数级别的容斥,还是没有理解容斥的思想,只知道基础的. 已经知道结果就在 ...

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

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

  6. HDU 5514 Frogs 欧拉函数

    题意: 有\(m(1 \leq m \leq 10^9)\)个石子排成一圈,编号分别为\(0,1,2 \cdots m-1\). 现在在\(0\)号石头上有\(n(1 \leq n \leq 10^4 ...

  7. HDU 5514 Frogs

    题意 有一群青蛙,一开始都在0点,有一堆圈石子,编号从0~m-1的. 青蛙只能顺时针跳,每个青蛙可以一次跳a[i]格,然后所有青蛙都这样一直跳下去,这些青蛙踩过的石子的编号和是多少? 思考 读了题,以 ...

  8. HDU - 5514 Frogs

    题目大意:有n只青蛙,每只青蛙的弹跳能力为ai,他们都从0出发,绕着m个石头围成的圈子跳跃,石头编号为0~m-1,问能被跳到的石头编号之和 具体思路:首先可以发现弹跳能力为ai的青蛙,可以跳到的石头编 ...

  9. Frogs HDU - 5514

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

最新文章

  1. Luogu P4479 [BJWC2018]第k大斜率
  2. 破windows xp登陆密码
  3. 机器学习(三)聚类深度讲解
  4. Everything Has Changed(HDU6354+圆交+求周长)
  5. css expression
  6. LeetCode 536. 从字符串生成二叉树(递归)
  7. I am BACKKKKKK
  8. 3 个 Zabbix常见问题的处理方法
  9. python---之suplot里面的twinx()函数
  10. 手机数控模拟器安卓版_CNC模拟器安卓中文版下载
  11. Python基础篇:Python的数据结构
  12. Https 证书相关
  13. 计算机产品校园营销方案,惠普笔记本电脑校园营销策划方案.doc
  14. Qt Creator vs2022 构建 Disney BRDF Explorer 项目
  15. python实验题目:中文数字对照表输入一个数字,转换成中文数字。比如:1234567890 -> 壹贰叁肆伍陆柒捌玖零。
  16. Visual.Assist.X.V10.7.1912的Crack破解补丁
  17. 基于AT89C51及Proteus仿真的室内火灾监测装置
  18. linux下合并多个文件夹内容成为一个文件夹
  19. 树莓派卸载系统自带应用增大硬盘空间
  20. 面向对象,类,属性,方法,创建调用属性方法,有参,无参,变量代码示例

热门文章

  1. java中对象输入流和输出流
  2. [深度学习-实践]BP神经网络的Helloworld(手写体识别和Fashion_mnist)
  3. ndarray的转置(numpy.transpose()与A.T命令对比详解)
  4. 深度神经网络可解释性:卷积核、权重和激活可视化(pytorch+tensorboard)
  5. leetcode —— 1290. 二进制链表转整数
  6. Git使用中报错fatal: The current branch master has no upstream branch.解决方案
  7. Java中String.split和StringUtils.split性能比较
  8. 修改mysql数据库编码(5.7版本)
  9. Java中Gamma、Beta等函数
  10. Python3解析XML文件(xml.etree.ElementTree)——以简单网络爬虫为例