题目

【题目描述】

克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。每个野人i有一个寿命值Li,即生存的年数。下面四幅图描述了一个有6个山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴编号依次为1,2,3;每年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。

奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?

【输入】

输入文件的第1行为一个整数N(1<=N<=15),即野人的数目。第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=10^6 ),表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。

【输出】

输出文件仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于10^6。

【样例输出】

3

1 3 4

2 7 3

3 2 1

【样例输出】

6

【提示】

该样例对应于题目描述中的例子。


题解

看完题目后,我忍不住吐槽一句——题目好烂!

题目中说野人群居,但是却又让野人单独居住,这还叫群居吗?!

好了,回归正题。这题一看就知道是一道数学题(废话),直接暴力是肯定不行的(废话)。

可以先枚举m,再枚举所有两个野人的情况,看看他们会不会在有生之年相遇在同一个山洞。

前面的枚举很简单,关键在于如何判断。

设野人 i 和野人 j 在第 x 年相遇,那么可以列出同余方程:

\[\begin{aligned}
C_i+P_i\cdot x & \equiv C_j+P_j\cdot x & \text{$(mod\space m)$}\\
C_i+P_i\cdot x & =C_j+P_j\cdot x+my & \text{(转化)}\\
P_i\cdot x-P_j\cdot x & =my+C_j-C_i & \text{(移项)}\\
(P_i-P_j)x-my & =Cj-Ci & \text{(化简)}
\end{aligned}
\]

设\(a=P_i-P_j\),\(b=-m\),\(c=C_j-C_i\),就可以把方程转化成以下形式:

\[\begin{aligned}
ax+by=c
\end{aligned}
\]

怎么样?眼熟吧!这就是扩展GCD

首先,可以在式子两边同时模\(\cfrac{c}{gcd(a,b)}\)(如果c不能整除gcd(a,b),那么方程无整数解,可直接退出),为什么?因为a和b一定是可以整除gcd(a,b)的,所以ax和by也一定可以整除它,ax+by也必定可以。

所以式子就变成了这个样子:

\[\begin{aligned}
ax+by&=gcd(a,b)\\
\because gcd(a,b)&=gcd(b,a\mod b)\\
\therefore ax+by&=bx+(a\mod b)y\\
\end{aligned}
\]

所以我们可以逐步递归下去,直到b=0(看下文)。

继续转换,得

\[\begin{aligned}
ax+by&=bx+(a\mod b)y\\
&=bx+(a-[\frac{a}{b}]b)y\\
&=bx+ay-[\frac{a}{b}]by\\
&=ay+b(x-[\frac{a}{b}]y)
\end{aligned}
\]

其中,[x]表示下取整x

由此,得

\[exgcd(ax+by)=exgcd(ay+b(x-[\frac{a}{b}]y))
\]

然后就可以这样递归下去了。

现在再来谈谈b=0的情况:

当b=0时,式子变成了\(ax=gcd(a,b)\)

显然\(a=gcd(a,b)\)(因为x是整数),即x=1,y=0

以下是扩展GCD的代码:

int exgcd(int a,int b)
{
if(b==0)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b),t;
t=x;x=y;y=t-a/b*y;
return d;
}

注意:扩展GCD的返回值是gcd(a,b)

由于x可能不是非负的最小解,因此我们要把它处理一下

x=x*cc/d%(b/d);
if(x<0) x+=abs(b/d);

前一句可以让x尽可能地靠近0,后一句可以让x非负。

最后判断一下两个野人可不可以在有生之年相遇,即看看是否\(x\le \min(l_i,l_j)\)

这题就搞定了。


代码

#include<cstdio>
using namespace std;
int c[20],p[20],l[20],x,y;
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}
inline int abs(int x){return x<0?0-x:x;}
int exgcd(int a,int b)
{
if(b==0)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b),t;
t=x;x=y;y=t-a/b*y;
return d;
}
int main()
{
int n,m=0,i,j,k,d,a,b,cc;
bool bk;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&c[i],&p[i],&l[i]);
m=max(m,c[i]);
}
for(k=m;k<=1e+6;k++)
{
bk=0;
for(i=1;i<n;i++)
{
for(j=i+1;j<=n;j++)
{
a=p[i]-p[j],b=k,cc=c[j]-c[i];
d=exgcd(a,b);
if(cc%d) continue;
x=x*cc/d%(b/d);
if(x<0) x+=abs(b/d);
if(x<=min(l[i],l[j]))
{
bk=1;
break;
}
}
if(bk) break;
}
if(!bk) break;
}
printf("%d\n",k);
return 0;
}

【扩展GCD】荒岛野人的更多相关文章

  1. bzoj1407 / P2421 [NOI2002]荒岛野人(exgcd)

    P2421 [NOI2002]荒岛野人 洞穴数不超过1e6 ---> 枚举 判断每个野人两两之间是否发生冲突:exgcd 假设有$m$个洞穴,某两人(设为1,2)在$t$时刻发生冲突 那么我们可 ...

  2. P1516 青蛙的约会和P2421 [NOI2002]荒岛野人

    洛谷 P1516 青蛙的约会 . 算是手推了一次数论题,以前做的都是看题解,虽然这题很水而且还交了5次才过... 求解方程\(x+am\equiv y+an \pmod l\)中,\(a\)的最小整数 ...

  3. UESTC 288 青蛙的约会 扩展GCD

    设两只青蛙跳了t步,则此时A的坐标:x+mt,B的坐标:y+nt.要使的他们在同一点,则要满足: x+mt - (y+nt) = kL (p是整数) 化成: (n-m)t + kL = x-y (L ...

  4. Poj 1061 青蛙的约会(扩展GCD)

    题目链接:http://poj.org/problem?id=1061 解题报告:两只青蛙在地球的同一条纬度线上,选取一个点位坐标轴原点,所以现在他们都在同一个首尾相连的坐标轴上,那么他们现在的位置分 ...

  5. poj 1061 青蛙的约会(扩展gcd)

    题目链接 题意:两只青蛙从数轴正方向跑,给出各自所在位置, 和数轴长度,和各自一次跳跃的步数,问最少多少步能相遇. 分析:(x+m*t) - (y+n*t) = p * L;(t是跳的次数,L是a青蛙 ...

  6. 2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

    题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展g ...

  7. BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS

    BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS 题意: 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p, ...

  8. 扩展gcd算法

    扩展gcd算法 神tm ×度搜索exgcd 打到exg的时候出来ex咖喱棒... 球方程\(ax+by=\gcd(a,b)\)的一个解 如果\(b=0\),那么\(\gcd(a,b)=a\),取\(x ...

  9. 扩展gcd codevs 1200 同余方程

    codevs 1200 同余方程 2012年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 求关 ...

随机推荐

  1. Killer Problem (UVA 11898 )

    Problem You are given an array of N integers and Q queries. Each query is a closed interval [l, r]. ...

  2. 28.Python list列表详解

    在实际开发中,经常需要将一些(不只一个)数据暂储起来,以便将来使用.说到这里,一些读者可能知道或听说过数组,它就可以把多个数据挨个存储到一起,通过数组下标可以访问数组中的各个元素.但使用数组存储数据有 ...

  3. CentOS7 安装JumpServer

    环境: CentOS Linux release 7.6.1810 (Core) JumpServer 1.4.8 Python 3.6.X MariaDB 编译安装Python3.6 首先,下载Py ...

  4. ant DatePicker 中文

    方式一:局部设置 import 'moment/locale/zh-cn'; import locale from 'antd/lib/date-picker/locale/zh_CN'; //调用时 ...

  5. Cortex-M3 在C中上报入栈的寄存器和各fault状态寄存器

    因为在标准C语音中是不能获取SP指针的.因而,如果想通过C代码来获取入栈的寄存器值,需要配合一小段汇编代码来获取当前的SP值,然后再把这个SP值以参数形式传送给C代码,最后以指针的形式把栈中的各寄存器 ...

  6. linux用户和组账户管理

    linux操作系统是一个多用户操作系统,它允许多用户同时登录到系统上并使用资源.系统会根据账户来区分每个用户的文件,进程,任务和工作环境,使得每个用户工作都不受干扰. 用户账户 A.普通用户账户:普通 ...

  7. SVN服务器的安装

    运行VisualSVN-Server-2.7.3.msi程序, 如下图 点击Next, 下一步 选中 I accept选项, 点击Next, 下一步 选择默认配置, 服务和控制台组件方式, 点击Nex ...

  8. java 抽取 word,pdf 的四种武器

    转自:https://www.ibm.com/developerworks/cn/java/l-java-tips/     感谢作者发布的文章 用 jacob 其实 jacob 是一个 bridag ...

  9. JavaScript日常学习1

    您会经常看到 document.getElementById("id"). 这个方法是 HTML DOM 中定义的. DOM (Document Object Model)(文档对 ...

  10. 阶段3 3.SpringMVC·_05.文件上传_4 文件上传之Springmvc方式上传代码

    后台提供新的方法,上传的方法复制一份传统上传的代码.改名为fileupload2 配置解析器 名字必须叫做myltipartResolver 里面可以配置一些属性,例如上传文件的大小等. 文件大小 最 ...