洛谷 P1516 青蛙的约会

算是手推了一次数论题,以前做的都是看题解,虽然这题很水而且还交了5次才过。。。

求解方程\(x+am\equiv y+an \pmod l\)中,\(a\)的最小整数解

\(0<x\neq y\leq 2\cdot 10^9,0<n,m\leq 2\cdot 10^9,0<l\leq 2.1\cdot 10^9\)


做一下变形:

\[x-y\equiv a(n-m) \pmod l
\]

设\(w=x-y,r=n-m\),则

\[ar\equiv w \pmod l
\]

此时,设\(\gcd(l,r)=gcd\),那么可以分两种情况

如果\(w\)是\(gcd\)的倍数,则原式可以写为:

\[ar'gcd\equiv w'gcd \pmod{l'gcd}
\]

根据同余式的性质,可以将\(gcd\)化简掉,具体证明在这里

\[ar'\equiv w'\pmod l'
\]

此时,\(\gcd(r',l')=1\),那么可以求出\(r' \bmod l'\)的逆元

那么\(w'r'^{-1}\bmod l'\)即为答案

具体操作就是用 exgcd,求出一个\(qr+pl=\gcd(r,l)\),然后可以表示为\(qr'gcd+pl'gcd=gcd\)

\(gcd\)被约掉,就是\(qr'+pl'=1\),则\(q\)即为\(r'\bmod l'\)的逆元

还有一种情况\(w\)不是\(gcd\)的倍数,显然无解

再就是注意\(w,r\)会不会出现负数,如果有负数在取模的时候可能会出现一些玄学情况,要现在\(\bmod l\)下把他们变成正的

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline LL read(){
LL x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
LL exgcd(LL &x,LL &y,LL a,LL b){
if(!b) return x=1,y=0,a;
LL gcd=exgcd(x,y,b,a%b);
int xx=x;x=y;
y=xx-a/b*y;
return gcd;
}
int main(){
LL n,m,x,y,l;
x=read();y=read();m=read();n=read();l=read();
if(m==n) return std::puts("Impossible"),0;
LL r=n-m,w=x-y;
if(r<0) r=(r+((-r/l)+1)*l)%l;
if(w<0) w=(w+((-w/l)+1)*l)%l;
LL a,b;
int gcd=exgcd(a,b,r,l);
if(w%gcd) return std::puts("Impossible"),0;
l/=gcd;w/=gcd;
std::printf("%lld",(w*a%l+l)%l);
return 0;
}

 

洛谷 P2421 [NOI2002]荒岛野人LOJ上也有

这题和上面那个几乎一样,代码复制过去改一改加个主函数就行

克里特岛以野人群居而著称。岛上有排列成环行的\(M\)个山洞。这些山洞顺时针编号为 \(1,2,\dots,M\)

岛上住着\(n\)个野人,一开始依次住在山洞 \(C_1,C_2,\dots,C_n\)中。以后每年,第 \(i\) 个野人会沿顺时针向前走 \(P_i\)个洞住下来。

每个野人\(i\)有一个寿命值 \(L_i\),即生存的年数。

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

这是真正的数据范围,洛谷上标的很乱:\(0<C_i,P_i\leq 100,1\leq N\leq 15,0\leq L_i\leq 10^6\)


把题意描述成数学语言,就是求一个最小的\(M\),使得对于任意的\(i\neq j,c_i+kp_i\equiv c_j+kp_j \pmod M\)无解,或解大于\(\min(L_i,L_j)\)

然后这个式子就和上面那个题一模一样了,就是记得判断解的大小就行

一开始想二分处理,然而发现并不满足可二分性,但保证\(M\leq 10^6\),很小,而且又保证有解,所以可以从\(\max c_i\)开始枚举\(M\),枚举到成立就行了

复杂度\(O(Mn^2\log C_i)\),超过\(10^9\)了,而且这还是02年的题,那时候恐怕测评机比现在也慢

不过肯定是跑不满,也不太可能会有什么毒瘤数据,估计是没有更优做法了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
register int x=0;register int y=1;
register char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int exgcd(int &x,int &y,int a,int b){
if(!b) return x=1,y=0,a;
LL gcd=exgcd(x,y,b,a%b);
int xx=x;x=y;
y=xx-a/b*y;
return gcd;
}
inline int check(int m,int n,int x,int y,int l,int min){//calc am+x = an+y mod l
if(m==n) return 0;
LL r=n-m,w=x-y;
if(r<0) r=(r+((-r/l)+1)*l)%l;
if(w<0) w=(w+((-w/l)+1)*l)%l;
int a,b;
int gcd=exgcd(a,b,r,l);
if(w%gcd) return 0;
w/=gcd;l/=gcd;
if((w*a%l+l)%l>min) return 0;
return 1;
}
int c[19],p[19],l[19];
int main(){
int n=read(),maxc=0;
for(reg int i=1;i<=n;i++) c[i]=read(),p[i]=read(),l[i]=read(),maxc=std::max(maxc,c[i]);
for(reg int m=maxc;;m++){
for(reg int i=1;i<=n;i++)
for(reg int j=i+1;j<=n;j++)
if(check(p[i],p[j],c[i],c[j],m,std::min(l[i],l[j]))) goto FAIL;
return std::printf("%d",m),0;
FAIL:;
}
return 0;
}

P1516 青蛙的约会和P2421 [NOI2002]荒岛野人的更多相关文章

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

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

  2. 【题解】洛谷P2421[NOI2002]荒岛野人 (Exgcd)

    洛谷P2421:https://www.luogu.org/problemnew/show/P2421 思路 从洞的最大编号开始增大枚举答案 对于每一个枚举的ans要满足Ci+k*Pi≡Cj+k*Pj ...

  3. 洛谷P2421 [NOI2002]荒岛野人(扩展欧几里得)

    题目背景 原 A-B数对(增强版)参见P1102 题目描述 克里特岛以野人群居而著称.岛上有排列成环行的M个山洞.这些山洞顺时针编号为1,2,…,M.岛上住着N个野人,一开始依次住在山洞C1,C2,… ...

  4. Luogu P2421 [NOI2002]荒岛野人

    最近上课时提到的一道扩欧水题.还是很可做的. 我们首先注意到,如果一个数\(s\)是符合要求的,那么那些比它大(or 小)的数不一定符合要求. 因此说,答案没有单调性,因此不能二分. 然后题目中也提到 ...

  5. P2421 [NOI2002]荒岛野人

    传送门 答案不大于 $10^6$,考虑枚举答案 对于枚举的 ans,必须满足对于任意 i,j(i≠j) 都有 使式子$c_i+kp_i \equiv c_j+kp_j\ (mod\ ans)$成立的最 ...

  6. P2421 [NOI2002]荒岛野人 扩展欧几里得 枚举

    Code: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...

  7. 洛谷 P2421 [NOI2002]荒岛野人

    题目描述 又是一道扩欧的题. 要求一个最小的m使得 Ci+Pi*x≡Cj+Pj*x mod m(i!=j) 在x在第i个人和第j个人的有生之年无解. 也就是 (Pi-Pj)*x+m*y=Cj-Ci 在 ...

  8. P1516 青蛙的约会

    P1516 青蛙的约会x+mt-p1L=y+nt-p2L(m-n)t+L(p2-p1)=y-x令p=p2-p1(m-n)t+Lp=y-x然后套扩欧就完事了 #include<iostream&g ...

  9. 洛谷 P1516 青蛙的约会 解题报告

    P1516 青蛙的约会 题目描述 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件 ...

随机推荐

  1. "多行文本"组件:<multi> —— 快应用组件库H-UI

     <import name="multi" src="../Common/ui/h-ui/text/c_text_multi"></impo ...

  2. Python Requests-学习笔记(6)-响应头

    响应头 我们可以查看以一个Python字典形式展示的服务器响应头: import requestsurl = 'http://httpbin.org/post'r = requests.get(url ...

  3. sparkRdd driver和excuter

    //1 从内存中创建makeRdd,底层实现就是parallelize val rdd=sc.makeRDD(Array(1,2,"df",55)) //2 从中创建paralle ...

  4. c++动态数组的优点,创建和删除

    动态数组可以有两种使用方式: 1:不能预先知道数组的大小使用动态数组 传统数组(静态数组)是需要在程序运行前,就指定大小,比如说 int i = 10; int a[i]; 这种就是不合法的. 因为函 ...

  5. 国外的一个代码 仓库 github --- 里面类似一个svn 的代码仓库

    https://github.com/wzhanke/shell 用户:wzh.e 邮箱:wzh.e@x.com 登陆密码:*wzh.e8*9

  6. web.xml被文件加载过程,各节点加载顺序总结

    web.xml被文件加载过程,各节点加载顺序总结 博客分类: J2EE WebXMLSpringServletBean  今天2010-3-11日,上班无事,想来将web.xml项目描述文件的加载过程 ...

  7. 数据结构和算法(Golang实现)(26)查找算法-哈希表

    哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...

  8. 011-指针(上)-C语言笔记

    011-指针(上)-C语言笔记 学习目标 1.[掌握]字符串常用函数 2.[掌握]指针变量的声明 3.[掌握]指针变量的初始化 4.[掌握]函数与指针 5.[掌握]指针的数据类型 6.[掌握]多级指针 ...

  9. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十一)之Holding Your Objects

    To solve the general programming problem, you need to create any number of objects, anytime, anywher ...

  10. Closest Common Ancestors POJ 1470

    Language: Default Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissio ...