欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Savage(扩展欧几里得)

程序员文章站 2024-02-11 16:44:58
...

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;
}