题目链接 : 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+; 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, , sizeof(vis));
memset(num, , sizeof(num));
} int main()
{
int t;
int n, m; scanf("%d", &t);
for(int cas = ; cas <= t; cas++) {
Init();
scanf("%d %d", &n, &m);
int cnt = ;
for(int i = ; i * i <= m; i++) {
if(m % i == ) {
d[cnt++] = i;
if(i * i != m) {
d[cnt++] = m / i;
}
}
}
sort(d, d+cnt, cmp);
for(int i = ; i < n; i++) {
scanf("%d", &a[i]);
a[i] = GCD(a[i], m);
for(int j = ; j < cnt; j++) {
if(d[j] % a[i] == ) {
vis[j] = ;
}
}
}
LL ans = ;
vis[cnt-] = ;
for(int i = ; i < cnt; i++) {
if(vis[i] != num[i]) {
LL temp = m / d[i];
ans += temp * (temp - ) / * d[i] * (vis[i] - num[i]);
for(int j = i + ; j < cnt; j++) {
if(d[j] % d[i] == ) {
num[j] += vis[i] - num[i];
}
}
}
}
printf("Case #%d: %I64d\n", cas, ans);
} return ;
}

HDU 5514 Frogs (容斥原理)的更多相关文章

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

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

  2. hdu 5514 Frogs(容斥)

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

  3. HDU 5514 Frogs(容斥原理)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5514 [题目大意] m个石子围成一圈,标号为0~m-1,现在有n只青蛙,每只每次跳a[i]个石子, ...

  4. HDU 5514 Frogs 容斥定理

    Frogs Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5514 De ...

  5. HDU 5514 Frogs

    Frogs Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: 5514 ...

  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 (数论容斥)

    题意:有n只青蛙,m个石头(围成圆圈).第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过的石头的下标总和是多少? 析:首先可以知道的是第 i 只青蛙可以跳到 k * gcd(ai, m),然后我就计 ...

  8. hdu 5514 Frogs 容斥思想+gcd 银牌题

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

  9. HDU 5514.Frogs-欧拉函数 or 容斥原理

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

随机推荐

  1. Linux read/write fread/fwrite两者区别

    Linux read/write fread/fwrite两者区别 1,fread是带缓冲的,read不带缓冲. 2,fopen是标准c里定义的,open是POSIX中定义的. 3,fread可以读一 ...

  2. POJ 1113 Wall 求凸包的两种方法

    Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31199   Accepted: 10521 Descriptio ...

  3. Python之路,Day25-----暂无正在更新中

    Python之路,Day25-----暂无正在更新中

  4. angular中ueditor插件的使用

    #在angularjs中使用ueditor编辑器需要注意事项: 在ui-view中使用放置ueditor的div,页面加载时编辑器在页面中是不显示的,需要通过指令手动replay 例: /** * u ...

  5. GIT学习(一)-->Git产生的历史原因

    首先要说:Git是目前世界上最先进的分布式版本控制系统(没有之一). git的作者:Linus,林纳斯(下图就是,先膜拜一下,因为成就可不止这一点) 他是为何要写git的呢?话说 Linus虽然创建了 ...

  6. My.Ioc 代码示例——使用条件绑定和元数据(可选)构建插件树

    本文旨在通过创建一棵插件树来演示条件绑定和元数据的用法. 说“插件树”也许不大妥当,因为在一般观念中,谈到插件树,我们很容易会想到 Winform/Wpf 中的菜单.举例来说,如果要在 Winform ...

  7. HTML5 离线缓存忽略主页实例

    默认情况下 指定html mianfest的当前页面会自动离线缓存到客户端. 取消的方法,可以使用iframe类实现 1.主页定义: <iframe frameborder="no&q ...

  8. Linux特殊权限

    ************************     ACL权限       ****************************************** acl权限的出现是为了弥补用户权 ...

  9. MySQL 创建数据库

    MySQL 创建数据库 使用 mysqladmin 创建数据库 使用普通用户,你可能需要特定的权限来创建或者删除 MySQL 数据库. 所以我们这边使用root用户登录,root用户拥有最高权限,可以 ...

  10. 设置Imindmap默认字体

    创建一个新的字体样式 根据如下步骤创建新的字体样式: 1.打开一个mindmap,选中工具栏上的 [样式][Styles ]. 2.选择 Font > Create New Font Optio ...