HDU 5514 Frogs
题意
有一群青蛙,一开始都在0点,有一堆圈石子,编号从0~m-1的。
青蛙只能顺时针跳,每个青蛙可以一次跳a[i]格,然后所有青蛙都这样一直跳下去,这些青蛙踩过的石子的编号和是多少?
思考
读了题,以为是暴力set过的,想到了之前set判重,Floyd判圈等等,结果遇到了MLE(第一次遇到),吓得我怀疑了set。
// MLE 2016-10-23#include<cstdio>
#include<cstring>
#include<set>
using namespace std;long long step[10010];int main()
{int kas, cnt = 1;scanf("%d",&kas);while(kas--){ set<long long> id;long long n, m;memset(step, 0, sizeof(step));scanf("%ld%ld",&n, &m);for(int i = 0; i<n; i++)scanf("%ld",&step[i]);for(int i = 0; i<n; i++){ long long ini = step[i]%m;set<long long> temp;while(!temp.count(ini)){ temp.insert(ini);// printf(" %ld marked\n",ini);ini = (ini+step[i])%m;}set<long long>::iterator temp_it;for(temp_it = temp.begin(); temp_it!=temp.end(); temp_it++)id.insert(*temp_it);}//cal sum of step[];set<long long>::iterator it;long long sum = 0;for(it = id.begin(); it!=id.end(); it++)sum+=*it;printf("Case#%d: %ld\n",cnt++, sum);}return 0;
}
然后果断搜索题解,看到了容斥定理,才了解这道题的类型,然后找到优化方法:
对于第i只青蛙,他跳过的格子,一定是k*gcd(a[i],m)这种的
如果m小一点,我们就可以直接暴力了
当时m太大了,我们就分解m的因数之后,对于每个因数做暴力就好了
每个因数T的贡献是 for(int i=1;i<=M/T;i++)ans += M*i;
第i只青蛙只能走到gcd(ai, m)的位置,我们就可以把m的因子提取出来,然后对青蛙能走到的因子位置打标记。(优化的关键) 青蛙能走到vis[i]因子位置就把vis[i]标记为1,然后num[i]表示m的第i个因子泪加的次数。如果vis[i]!=num[i]的话,就更新num。因子的个数大概是log2(m),所以时间复杂度大概为O(log2(m)2)。
当然也可以用set,但直接set不行。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const int maxn = 100010;int p[maxn], vis[maxn], num[maxn];
int gcd (int a, int b)
{return b==0 ? a : gcd(b, a%b);
}int main ()
{int T;scanf ("%d", &T);for (int t=1; t<=T; t++){int n, m, cnt = 0;scanf ("%d %d", &n, &m);for (int i=1; i<=sqrt(m); i++){if (m % i == 0){p[cnt ++] = i;if (i * i != m)p[cnt ++] = m / i;}}sort (p, p+cnt);int u;memset (vis, 0, sizeof(vis));memset (num, 0, sizeof(num));for (int i=0; i<n; i++){scanf ("%d", &u);int temp = gcd (u, m);for (int j=0; j<cnt; j++){if (p[j] % temp == 0)vis[j] = 1;}}vis[cnt-1] = 0;LL ans = 0;for (int i=0; i<cnt; i++){if (vis[i] != num[i]){LL temp = m / p[i];ans += temp * (temp - 1) / 2 * p[i] * (vis[i] - num[i]);temp = vis[i] - num[i];for (int j=i; j<cnt; j++)if (p[j] % p[i] == 0)num[j] += temp;}}printf ("Case #%d: %I64d\n", t, ans);}return 0;
}
HDU 5514 Frogs相关推荐
- HDU 5514 Frogs (容斥原理)
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5514 题意 : 有m个石子围成一圈, 有n只青蛙从跳石子, 都从0号石子开始, 每只能越过a[i] ...
- HDU 5514 Frogs
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5514 题目描述: 有n只青蛙,m个石头(围成圆圈).第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过 ...
- HDU 5514 Frogs 容斥
http://acm.hdu.edu.cn/showproblem.php?pid=5514 没有想到怎么利用gcd的性质来改进指数级别的容斥,还是没有理解容斥的思想,只知道基础的. 已经知道结果就在 ...
- HDU 5514 Frogs 欧拉函数
题意: 有\(m(1 \leq m \leq 10^9)\)个石子排成一圈,编号分别为\(0,1,2 \cdots m-1\). 现在在\(0\)号石头上有\(n(1 \leq n \leq 10^4 ...
- HDU 5514 Frogs(欧拉函数+数论YY)
传送门 Frogs Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
- HDU 5514 Frogs (容斥原理+因子分解)
题目链接 题意:有n只青蛙,m个石头(围成圆圈).第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过的石头的下标总和是多少? 题解:暴力肯定会超时,首先分解出m的因子,自己本身不用分,因为石头编号是0 ...
- HDU - 5514 Frogs(容斥原理)
题目链接:点击查看 题目大意:给出 0 ~ m - 1 共 m 个石头首尾相连呈现出一个环状,初始时在第 0 个石头上有 n 只青蛙,n 只青蛙相互独立,每一只青蛙每次都会向前跳 a[ i ] 步,问 ...
- HDU - 5514 Frogs
题目大意:有n只青蛙,每只青蛙的弹跳能力为ai,他们都从0出发,绕着m个石头围成的圈子跳跃,石头编号为0~m-1,问能被跳到的石头编号之和 具体思路:首先可以发现弹跳能力为ai的青蛙,可以跳到的石头编 ...
- Frogs HDU - 5514
Frogs HDU - 5514 题意: 有n个青蛙,第 i 个青蛙每次只能够跳 ai步,现在有m个石头围成一圈,编号为0到m−1,现在青蛙可以围着这个石头组成的圆跳无限次,每跳一次就会占领这个石头 ...
最新文章
- 异常规范之阿里巴巴开发手册中的异常规范讲解
- 第十八章 12判断string类型字符串是否为空
- 北理工计算机学院新闻,北理工计算机学子勇夺CVPR 2021 AI安全国际顶级赛事季军...
- P3311-[SDOI2014]数数【AC自动机,dp】
- CC2540 串口0 通道2配置
- 【大数据新手上路】“零基础”系列课程--MySQL 数据整库迁移到 MaxCompute
- spark的异步消息总线LiveListenBus
- 设置mysql密码 Access denied 问题
- 开发人员常用的Oracle导入/导出命令
- 在php中使用Memcache
- href 和 src 区别
- sqlserver安装目录_SQL 2008R2安装教程
- 在Excel中快速制作分区桌面壁纸
- C#获取单个字符的拼音声母
- 走近“领域特定语言”(Domain-Specific Languages)
- MQTT协议之连接和心跳
- 如何pip更新所有包?
- 我终于有了GMAIL帐号了
- NIR近红外光谱简介
- xenserver内核的linux版本,XenServer7.0创建本地ISO库