BZOJ 1407

1407: [Noi2002]Savage

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 2350  Solved: 1054
[Submit][Status][Discuss]

Description

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
//该样例对应于题目描述中的例子。

Source

鸣谢刘汝佳先生授权使用

HINT

 很容易发现是解一个同余方程k(p[j]-p[i])=c[i]-c[j] mod x(枚举x)只要解小于l[i]和l[j]就不满足条件
 数据小,随便枚举
扩展欧几里得!!
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 20
using namespace std;
int n,c[N],p[N],l[N],k;
void exgcd(int a,int b,int &d,int &x,int &y)
{
    if(b==0)
    {
        d=a;x=1;y=0;
    }
    else
    {
        exgcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
int ok(int mod)
{
    for(int i=1;i<=n-1;i++)
        for(int j=i+1;j<=n;j++)
        {
            int a=((p[i]-p[j])%mod+mod)%mod,b=((c[j]-c[i])%mod+mod)%mod,x,y,d;
            exgcd(a,mod,d,x,y);
            
            //printf("%d %d %d %d %d
",a,mod,d,x,y);
            
            if(b%d!=0)continue;
            b/=d; int mm=mod/d;
            int ans=((b*x)%mm+mm)%mm;
            if(ans<=min(l[i],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]);
        k=max(k,c[i]);
        c[i]--;
    }
    for(;;k++)
        if(ok(k))
        {
            printf("%d",k);
            return 0;
        }
    return 0;
}
原文地址:https://www.cnblogs.com/fdfzhyf/p/8125232.html