1. 程式人生 > >Savage(擴充套件歐幾里得)

Savage(擴充套件歐幾里得)

Savage

Input
第1行為一個整數N(1<=N<=15),即野人的數目。
第2行到第N+1每行為三個整數Ci, Pi, Li表示每個野人所住的初始洞穴編號,每年走過的洞穴數及壽命值。
(1<=Ci,Pi<=100, 0<=Li<=10^6 )
Output
僅包含一個數M,即最少可能的山洞數。輸入資料保證有解,且M不大於10^6。

Sample Input
3
1 3 4
2 7 3
3 2 1
Sample Output
6
//該樣例對應於題目描述中的例子。

題解:
由於洞穴是環狀的,所以聯想到mod。
看到答案不超過1e6,所以可以從小到大列舉ans,看看每個ans是否合法,如果合法就直接輸出。
首先如果沒有壽命的限制,那我們可以列出同餘方程ci+pi*x≡cj+pj*x(mod ans)(1<=i,j<=n),如果合法的話,說明x是無解的。
但是題目中每個人壽命,所以要做一些改變,也就是說當ans合法的時候不僅有上面那個同餘方程無解,也可以解出來的x>min(li,lj)

程式碼如下

#include <cstdio>
#include <algorithm>
using namespace std;
int n,c[20],p[20],l[20],ax;
void exgcd(int a,int b,int &g,int &x,int &y){
    if (!b) g=a,x=1,y=0;
    else exgcd(b,a%b,g,y,x),y-=x*(a/b);
}
bool pd(int A){
    for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++){
        int
a=((p[i]-p[j])%A+A)%A,b=((c[j]-c[i])%A+A)%A,x,y,G,F; exgcd(a,A,G,x,y);if (b%G) continue;b/=G;F=A/G; x=(b*x%F+F)%F;if (x<=l[i] && x<=l[j]) return 0; } return 1; } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d%d%d",&c[i],&p[i],&l[i]),ax=max(c[i],ax); for
(int i=ax;;i++) if (pd(i)) {printf("%d\n",i);return 0;} return 0; }