传送门

Frogs

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2198    Accepted Submission(s): 714

Problem Description
There are $m$ stones lying on a circle, and $n$ frogs are jumping over them.
The stones are numbered from $0$ to $m-1$ and the frogs are numbered from $1$ to $n$. The $i$-th frog can jump over exactly $a_i$ stones in a single step, which means from stone $j~mod~m$ to stone $(j+a_i)~mod~m$ (since all stones lie on a circle).

All frogs start their jump at stone $0$, then each of them can jump as many steps as he wants. A frog will occupy a stone when he reach it, and he will keep jumping to occupy as much stones as possible. A stone is still considered ``occupied" after a frog jumped away.
They would like to know which stones can be occupied by at least one of them. Since there may be too many stones, the frogs only want to know the sum of those stones' identifiers.

Input
There are multiple test cases (no more than $20$), and the first line contains an integer $t$,
meaning the total number of test cases.

For each test case, the first line contains two positive integer $n$ and $m$ - the number of frogs and stones respectively $(1\le n\le 10^4,~1\le m\le 10^9)$.

The second line contains $n$ integers $a_1,a_2,\cdots,a_n$, where $a_i$ denotes step length of the $i$-th frog $(1\le a_i\le 10^9)$.

Output
For each test case, you should print first the identifier of the test case and then the sum of all occupied stones' identifiers.
Sample Input
3 2 12 9 10 3 60 22 33 66 9 96 81 40 48 32 64 16 96 42 72
Sample Output
Case #1: 42 Case #2: 1170 Case #3: 1872

题目大意:
有 nnn 个青蛙,第 iii 个青蛙每次只能够跳 aia_iai​ 步,现在有 mmm 个石头围成一圈,编号为 0到m−10\ 到\ m-10 到 m−1,现在青蛙可以围着这个石头组成的圆跳无限次,每跳一次就会占领这个石头,可以无限占领,现在问你的是这 nnn 个青蛙占领的石头的编号的总和是多少。

解题思路:

首先能够想到的是: 第 iii 个青蛙能够跳的步长一定是 gi=GCD(m,ai)g_i=GCD(m,a_i)gi​=GCD(m,ai​),所以能占领的石头的编号就是 gig_igi​ 的倍数,就拿第一个样例来说吧:

2 12
9 10

对于第一只青蛙来说 g1=GCD(12,9)=3g_1=GCD(12,9)=3g1​=GCD(12,9)=3,所以步长为 333, 那么他能跳的石头编号就是 0,3,6,90,3,6,90,3,6,9
对于第二只青蛙来说 g2=GCD(12,10)=2g_2=GCD(12,10)=2g2​=GCD(12,10)=2,所以步长为 222, 那么他能跳的石头编号就是 0,2,4,6,8,100,2,4,6,8,100,2,4,6,8,10
显然第一只青蛙和第二只青蛙占领的石头编号有重复的地方,那么我们为了消除这些重复的值,我们规定第 iii 个石头只能由 GCD(m,i)GCD(m,i)GCD(m,i) 的步长的来占领。那么就有:
2,102,102,10 只能由步长为 222 的来占领;
3,93,93,9 只能由步长为 333 的来占领;
4,84,84,8 只能由步长为 444 的来占领;
666 只能由步长为 666 的来占领;
这样的话,就消除了重复的地方,现在问题就是怎么计算这样的和。
显然这些步长是由 <m\lt m<m 的 mmm 的因子组成,那么我们首先把这些因子预处理出来,然后判断该因子是否符合条件,即是不是能够被gcd(m,ai)gcd(m,a_i)gcd(m,ai​) 中的一个整除,在然后我们将这些步长当成公共因子提出来发现:
2+10=2∗(1+5)2+10=2*(1+5)2+10=2∗(1+5)
3+9=3∗(1+3)3+9=3*(1+3)3+9=3∗(1+3)
4+8=4∗(1+2)4+8=4*(1+2)4+8=4∗(1+2)
6=6∗16=6*16=6∗1
对于步长为 xxx 的求和来说,就是 x∗(与mx互素的个数的和)x*(与\frac m x互素的个数的和)x∗(与xm​互素的个数的和)
需要知道一个结论:
在 [1,x][1,x][1,x] 中与 xxx 互素的数的和为: Phi(x)∗x2\frac {Phi(x)*x}22Phi(x)∗x​
那么显然有:
对于步长为 xxx 的求和来说,x∗Phi(mx)∗mx2x*\frac{Phi(\frac m x)*\frac m x}2x∗2Phi(xm​)∗xm​​
整理得:
Phi(mx)∗m2\frac{Phi(\frac m x)*m}22Phi(xm​)∗m​
所以最终的结果就是: ∑Phi(mx)∗m2\sum \frac{Phi(\frac m x)*m}2∑2Phi(xm​)∗m​

扩展:
对于在 [1,x][1,x][1,x] 中与 xxx 互素的数的和为: Phi(x)∗x2\frac {Phi(x)*x}22Phi(x)∗x​ 的简单证明:
对于 gcd(x,i)=gcd(x,x−i)gcd(x,i)=gcd(x,x-i)gcd(x,i)=gcd(x,x−i)
那么就是成对出现的,不会出现相同的结果, 即i=x−ii=x-ii=x−i
假设这个成立那么有 x=2∗ix=2*ix=2∗i, gcd(x,i)=igcd(x,i)=igcd(x,i)=i,与已知矛盾,所以不成立,
那么显然 gcd(x,i)=1gcd(x,i)=1gcd(x,i)=1 的个数为 Phi(x)Phi(x)Phi(x) 个,然后gcd(x,i)=1gcd(x,i)=1gcd(x,i)=1 的与 gcd(x,x−i)=1gcd(x,x-i)=1gcd(x,x−i)=1 的合并就有:
与 xxx 互素的和就是 Phi(x)∗x2\frac {Phi(x)*x}22Phi(x)∗x​
代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>using namespace std;
typedef long long LL;
const LL MAXN = 1e4+5;LL gcd(LL a, LL b){if(b == 0) return a;return gcd(b, a%b);
}
LL a[MAXN], fac[MAXN], g[MAXN];
LL Phi(LL x){LL ans = x;for(LL i=2; i*i<=x; i++){if(x%i==0){ans -= ans/i;while(x%i==0) x /= i;}}if(x > 1) ans -= ans/x;return ans;
}
int main()
{int T;scanf("%d", &T);for(int cas=1; cas<=T; cas++){int n; LL m; scanf("%d%lld",&n, &m);int ok = 0;for(int i=0; i<n; i++){scanf("%lld",&a[i]);g[i] = gcd(a[i], m);if(g[i] == 1) ok = 1;}printf("Case #%d: ",cas);if(ok == 1){printf("%lld\n",m*(m-1)/2);continue;}sort(g, g+n);n = unique(g, g+n) - g;int cnt = 0;for(LL i=2; i*i<=m; i++){if(i*i == m) fac[cnt++] = m/i;else if(m%i==0) fac[cnt++] = i, fac[cnt++] = m/i;}sort(fac, fac+cnt);LL sum = 0;for(int i=0; i<cnt; i++){for(int j=0; j<n; j++){if(fac[i]%g[j] == 0){sum += Phi(m/fac[i])*m/2;break;}}}printf("%lld\n",sum);}return 0;
}
/**
2
9 96
81 40 48 32 64 16 96 42 72
*/

补:
现在更新一种容斥原理的做法,最开始的时候,我也想到容斥了,可是后来精度爆炸就没怎么想了,现在补一下:
现在我们已知 gi=gcd(m,ai)g_i=gcd(m, a_i)gi​=gcd(m,ai​), 我们还是考虑 mmm 的因子xxx,如果这个因子 xxx 符合条件,那么我们来计算 xxx 对答案做出的贡献: (mx−1)∗m2\frac {(\frac m x-1)*m}22(xm​−1)∗m​。
首先我们预处理出 mmm 的除了 1和m1\ 和\ m1 和 m 的因子 fac[i]fac[i]fac[i],如果这个因子fac[i]%g[i]=0fac[i]\%g[i]=0fac[i]%g[i]=0 的话(其中 g[i]g[i]g[i]为可能出现的最大公约数),那么我们将其用一个 visvisvis 数组进行标记为 111,然后再用一个数组 numnumnum 记录当前因子对答案做过的贡献,初始值为 000,那么有第iii 个因子做出的贡献为: (mx−1)∗m2∗(vis[i]−num[i])\frac {(\frac m x-1)*m}2*(vis[i]-num[i])2(xm​−1)∗m​∗(vis[i]−num[i])
因为可能有重复的,所以我们就对所有能够整除因子 fac[i]fac[i]fac[i] 的因子全都加上 vis[i]−num[i]vis[i]-num[i]vis[i]−num[i], 然后就可以计算答案了。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>using namespace std;
typedef long long LL;
const int MAXN = 1e4+5;
LL gcd(LL a, LL b){if(b == 0) return a;return gcd(b, a%b);
}
LL g[MAXN], fac[MAXN];
int tp[MAXN], num[MAXN], vis[MAXN];
int main()
{int T;scanf("%d", &T);for(int cas=1; cas<=T; cas++){int n; LL m; scanf("%d%lld",&n, &m);int ok = 0;for(int i=0; i<n; i++){scanf("%lld",&g[i]);g[i] = gcd(g[i], m);if(g[i] == 1) ok = 1;}printf("Case #%d: ",cas);if(ok == 1){printf("%lld\n",m*(m-1)/2);continue;}sort(g, g+n);n = unique(g, g+n) - g;memset(vis, 0, sizeof(vis));memset(num, 0, sizeof(num));int cnt = 0;for(LL i=2; i*i<=m; i++){if(i*i == m) fac[cnt++] = m/i;else if(m%i==0) fac[cnt++] = i, fac[cnt++] = m/i;}sort(fac, fac+cnt);int cnt1 = 0;for(int i=0; i<n; i++){if(!vis[i]){tp[cnt1++] = g[i];for(int j=0; j<n; j++)if(g[j]%g[i]==0) vis[j] = 1;}}memset(vis, 0, sizeof(vis));for(int i=0; i<cnt; i++){for(int j=0; j<cnt1; j++){if(fac[i]%tp[j] == 0){vis[i] = 1;break;}}}LL sum = 0;for(int i=0; i<cnt; i++){if(num[i] != vis[i]){sum += m*(m/fac[i]-1)/2*(vis[i]-num[i]);for(int j=i+1; j<cnt; j++)if(fac[j]%fac[i] == 0)num[j] = num[j] + vis[i] - num[i];}}printf("%lld\n",sum);}return 0;
}

HDU 5514 Frogs(欧拉函数+数论YY)相关推荐

  1. HDU 5514 Frogs 欧拉函数

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

  2. hdu 4983(欧拉函数)

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

  3. P2158,jzoj1709-仪仗队【欧拉函数,数论】

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P2158 大意 有n∗nn∗nn*n个点,求从(1,1)(1,1)(1 ...

  4. Bzoj 2749: [HAOI2012]外星人 欧拉函数,数论,线性筛

    2749: [HAOI2012]外星人 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 568  Solved: 302 [Submit][Status ...

  5. 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, ...

  6. jzoj1164-求和【欧拉函数,数论】(筛欧拉函数模板)

    正题 大意 给出一个nnn,求1∼n" role="presentation" style="position: relative;">1∼n1 ...

  7. CCPC-2017 杭州站B丨HDU - 6265丨数论丨积性函数 丨欧拉函数丨狄利克雷卷积丨思维变换

    [参考博客]@WJHKDGHP ccpc2017杭州站 B [参考博客]@灬从此以后灬 2017 CCPC 杭州 HDU6265B 积性函数 特别感谢以上两位博主,让我看懂了许多细节. 交题网址(HD ...

  8. hdu 1286( 欧拉函数 )

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

  9. hdu1395 数论 欧拉函数

    hdu1395 数论   欧拉函数 对于给出的每一个n 求最小正整数 x 满足 2^x mod n = 1 1.如果给出的n 是偶数或者 1 则一定无解 2.如果是奇数 首先根据欧拉定理 我们可知 p ...

最新文章

  1. 第四范式上榜《麻省理工科技评论》“50家聪明公司”榜单
  2. Gingko——百度内网用于数据分发的P2P传输工具
  3. System.FormatException: GUID 应包含带 4 个短划线的 32 位数(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。...
  4. GitHub 贡献第一的微软开源软件列表
  5. JDK内置的进制转换
  6. 【java】基于JWT的token身份认证方案
  7. bzoj1770: [Usaco2009 Nov]lights 燈(折半搜索)
  8. 自媒体人本质是互联网公司内容运营的角色
  9. 【ROS学习笔记】(七)服务端Server的实现
  10. ArcGIS 10 SDE for ORACLE ---迁移 (1)
  11. 防火墙和IPS有什么区别
  12. linux u盘启动制作教程,cdlinux u盘启动制作教程
  13. 无线路由器桥接——手机连不上网
  14. 什么是 Google Play服务
  15. 彩色图、灰度图和二值图
  16. 降噪蓝牙耳机哪个品牌好?降噪蓝牙耳机排行推荐
  17. yocto(五)——构建SDK及添加工具链
  18. 机构视角筛选底部平台突破股票
  19. linux裸设备文件系统,关于裸设备,文件系统,CIO/DIO
  20. linux下下载openwrt源码,OpenWrt下载编译

热门文章

  1. 如何做好疫情防控档案管理工作
  2. Centos7 安装配置MySQL5.7
  3. access 报表隔行底纹_请问高手:如何快速实现工作表的隔行底纹设置 – 手机爱问...
  4. 抖音主页位置怎么自己创建服务器手机版,抖音位置怎么自己创建_添加位置方式大全...
  5. [CTF]GUET梦极光杯线下赛web部分WP
  6. 《医疗保障法》将落地 五大细节解读速看
  7. 备品备件库存:建立关系图谱,实现良性管理
  8. CentOS8用户和组管理
  9. Visual Studio 2017 Installer Projects
  10. 设计模式-行为型模式-Observer 观察者模式