NOI2002荒島野人 (savage) 擴充套件歐幾里得
阿新 • • 發佈:2021-02-17
技術標籤:c++
分析
假設野人i,j在某一年相遇了,則出現:
m
a
n
[
i
]
.
c
+
x
∗
m
a
n
[
i
]
.
p
≡
m
a
n
[
j
]
.
c
+
x
∗
m
a
n
[
j
]
.
p
(
m
o
d
m
)
man[i].c+x∗man[i].p\equiv man[j].c+x∗man[j].p(\bmod m)
man[i].c+x∗man[i].p≡man[j].c+x∗man[j].p(modm)
如果要讓他們不相遇,則需要讓這個同餘方程無解,或解出的最小的x比兩個人中任何一人的壽命長。
將上式變形得到:
x
∗
(
m
a
n
[
i
]
.
p
−
m
a
n
[
j
]
.
p
)
−
y
∗
m
=
(
m
a
n
[
j
]
.
c
−
m
a
n
[
i
]
.
c
)
x∗(man[i].p-man[j].p)-y*m = (man[j].c-man[i].c)
x∗(man[i].p−man[j].p)−y∗m=(man[j].c−man[i].c)
令a=man[i].p-man[j].p,b=man[j].c-man[i].c
原式變為:
x
∗
a
−
y
∗
m
=
b
x*a-y*m=b
x∗a−y∗m=b
解得d如果不能被b整除,說明無解,繼續向下判斷(continue);
否則求出最小的x,如果x小於0,則需要+abs(m/d)求出大於0的最小值。
判斷此時x和兩個野人的生存時間關係,最小的x比兩個人中任何一人的壽命長 不成立,直接退出.
C++ 程式碼
#include<bits/stdc++.h> using namespace std; typedef long long LL; int n,m; struct node{ int c,p,l; }man[20]; LL exgcd(LL a,LL b,LL &x,LL &y) { if(!b) { x=1ll,y=0; return a; } LL d=exgcd(b,a%b,y,x); y-=a/b*x; return d; } bool flag; bool jdg(int x,int i,int j) { flag=true; if (x<=min(man[i].l,man[j].l)) //最小的x比兩個人中任何一人的壽命長 不成立,直接退出 { flag=false; return false; } return true; } int main() { cin>>n; for(int i=0;i<n;i++) { cin>>man[i].c>>man[i].p>>man[i].l; m=max(m,man[i].c); } if(n==1) //只有一個野人,則只需要一個洞 { puts("1"); return 0; } while(1) { flag=true; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { LL x,y,a,b; a=man[i].p-man[j].p; b=man[j].c-man[i].c; LL d=exgcd(a,m,x,y); if(b%d) continue; //無解,繼續判斷 x*=b/d; x=x%(m/d); if(x<0) x+=abs(m/d); if(!jdg(x,i,j)) break; } if(!flag) break; } if(flag) //所有野人的關係均成立,則輸出這個m { cout<<m<<endl; return 0; } m++; //m++進入下一次大迴圈 } return 0; }