HDU
来源:互联网 发布:人工智能创意文案 编辑:程序博客网 时间:2024/06/16 21:32
题目描述:
点击打开链接
题意,有m个石头,标号从0-m-1,有n只青蛙,所有青蛙一开始都在编号为0的石头上,每只青蛙每次可以跳的距离为a[i],青蛙每跳到一个石头上就会占领这个石头,求所有青蛙能够占领的石头的编号之和。
首先考虑对于每个青蛙他能够占领的所有石头都是gcd(a[i],m)的倍数,那么对于m以内gcd(a[i],m)的所有倍数实际上是一个等差数列,我们可以通过等差数列求和求的对于一个青蛙,设gcd(a[i],m)=x,它所经过的所有石头的编号和为(x+x*(m/x-1))*(m/x-1)/2=x*(m/x)*(m/x-1)/2,这里的(m/x-1)需要解释一下,首先gcd(a[i],m)=x,这个x一定是m的因子的所以一定能够整除,有这题的编号是从0-m-1,所有m这个石头是不算的,所以要把这个石头减去。然后对于每只青蛙我们都可以这样算出一个和,但是里面有重复的部分,这就涉及到麻烦的去重。关于的去重的部分,我的处理时,先将m的所有因子枚举出来,然后对于要计算的因子进行标记,进行计算时需要同时统计其他因子已经计算的次数,对于多计算的需要减掉,少计算的加上。详见代码注释。
AC代码:
#include<iostream>#include<sstream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<set>#include<queue>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;const int MAXM=100010;long long n,m,cnt;long long a[MAXM];long long vis[MAXM];long long num[MAXM];/*void init(){ memset(prime,true,sizeof(prime)); prime[2]=true; cnt=0; for (int i=2;i<MAXM;i++) { if (prime[i]) { rec[cnt++]=i; for (int j=i*2;j<MAXM;j=j+i) prime[j]=false; } }}*/long long gcd(long long x,long long y){ return y==0? x:gcd(y,x%y);}int main(){ int T; scanf("%d",&T); int cas=1; while(T--) { scanf("%lld%lld",&n,&m); int cnt=0; for (long long i=1;i*i<=m;i++) { if (m%i==0) { a[cnt++]=i; if (i*i!=m) a[cnt++]=m/i; } } sort(a,a+cnt); long long x; memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num));//num数组用来计算每个因子已经被计算了多少次。 for (int i=1;i<=n;i++) { scanf("%d",&x); x=gcd(x,m); for (int j=0;j<cnt-1;j++) if (a[j]%x==0) vis[j]=1;//这个标记表示这个应该被计算几次,所有出现过的因子都应该被计算一次,没有出现过的不应该被计算。 } long long ans=0; for (int i=0;i<cnt-1;i++) { if (num[i]!=vis[i]) {//如果已经被计算的次数与应该被计算的次数不等说明我们需要继续进行计算。 ans+=((m/a[i])*(m/a[i]-1)/2)*a[i]*(vis[i]-num[i]);//vis[i]-num[i]表示如果之前被多计算了需要减去,少计算了需要被加上。 long long tmp=vis[i]-num[i]; for (int j=i;j<cnt-1;j++) {//对于其他因子的标记,这个应该好理解,比如我在计算2的倍数的时候,实际上4,6,8等2的倍数都已经被计算过一次了,那么我们就需要记录这些倍数的因子被多算或少算的次数。 if (a[j]%a[i]==0) num[j]+=tmp; } } } printf("Case #%d: %lld\n",cas,ans); cas++; } return 0;}
阅读全文
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- LinuxStudyNote(33)-Linux常用命令(8)-mount挂载命令、umount卸载命令
- angular4 服务依赖注入的三种方法
- linux常用操作命令及linux系统目录结构
- [agc015e]Mr.Aoki Incubator
- python笔记003--python的运行方式
- HDU
- 享元模式
- 这是我的第一个博客
- 数据结构实验之链表一:顺序建立链表
- 安装Ubuntu Linux系统时硬盘分区最合理的方法
- ZooKeeper系列(二)
- java学习记录——整数累加及阶乘累加
- AKKA并发编程简介
- 判断一棵二叉树是不是对称的