一本通1637荒岛野人

1637:荒岛野人

Description

Input

第1行为一个整数N(1<=N<=15),即野人的数目。第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=106 ),表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。

Output

仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于106。

Sample Input

3
1 3 4
2 7 3
3 2 1

Sample Output

6

该样例对应于题目描述中的例子。

 

sol:感觉挺难的,想了好久吧。。

原式:
C[i]+k*P[i] = C[j]+k*P[j] (%Mod)
使得该式的解k无解或k>min(L[i],L[j])

转化
C[i]+k*P[i] = C[j]+k*P[j] (%Mod)
k*(P[i]-P[j]) = C[j]-C[i] (%Mod)
k*(P[i]-P[j])+x*Mod = C[j]-C[i] (类ax+by=c的形式) (要求的是k和x)

然后暴力枚举答案,n2判断即可

Ps:实现的时候有个细节要注意,式子里的k不能是0,

/*
原式: 
C[i]+k*P[i] = C[j]+k*P[j] (%Mod)
使得该式的解k无解或k>min(L[i],L[j])

转化
C[i]+k*P[i] = C[j]+k*P[j] (%Mod)
k*(P[i]-P[j]) = C[j]-C[i] (%Mod)
k*(P[i]-P[j])+x*Mod = C[j]-C[i] (类ax+by=c的形式) (要求的是k和x)
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
/*
    k*(P[i]-P[j])+x*Mod = C[j]-C[i]
*/
const int N=20;
int n,C[N],P[N],L[N];
inline ll gcd(ll x,ll y)
{
    return (!y)?(x):(gcd(y,x%y));
}
inline void Exgcd(ll a,ll b,ll &X,ll &Y)
{
    if(b==0)
    {
        X=1;
        Y=0;
        return;
    }
    Exgcd(b,a%b,X,Y);
    ll XX=X,YY=Y;
    X=YY;
    Y=XX-a/b*YY;
    return;
}
inline bool Solve(ll Mod)
{
    int i,j;
    for(i=1;i<n;i++)
    {
        for(j=i+1;j<=n;j++)
        {
            ll a=P[i]-P[j],b=Mod,c=C[j]-C[i];
            ll r=gcd(a,b),X,Y;
            if(c%r==0) // 无解挺好的 
            {
                Exgcd(a,b,X=0,Y=0);
                X=X/r*c;
                ll tmp=abs(b/r);
                X=(X%tmp+tmp)%tmp;
                if(!X) X+=tmp;
                if(X<=min(L[i],L[j])) return 0;
            }
        }
    }
    return 1;
}
int main()
{
    int i,m;
    R(n);
    for(i=1;i<=n;i++)
    {
        R(C[i]); R(P[i]); R(L[i]);
        m=max(m,C[i]);
    }
    for(i=m;;i++)
    {
        if(Solve(i))
        {
            Wl(i); break;
        }
    }
    return 0;
}
/*
input
3
1 3 4
2 7 3
3 2 1
output
6
*/
View Code

 

posted @ 2019-03-04 23:06  yccdu  阅读(272)  评论(0编辑  收藏  举报