1407: [Noi2002]Savage
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1234 Solved: 559
[ Submit][ Status][ Discuss]
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
1 3 4
2 7 3
3 2 1
Sample Output
6
该样例对应于题目描述中的例子。
该样例对应于题目描述中的例子。
HINT
Source
题解:刚看到这道题时有点毫无头绪,想到了扩展欧几里得算法,但是由不知道该怎么搞。直到看到题目描述中的
输入数据保证有解,且M不大于10^6。
这句话才想到怎么做,直接暴力枚举山洞的个数,然后判断是否可行就好了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,a[20],c[20],p[20],maxn;
int fx,fy;
int gcd(int x,int y)
{
int r;
while (y!=0)
{
r=x%y;
x=y;
y=r;
}
return x;
}
void exgcd(int a,int b)
{
if (b==0)
{
fx=1;fy=0;return;
}
exgcd(b,a%b);
int t=fy;
fy=fx-(a/b)*fy; fx=t;
}
bool work(int x)
{
int k=0; int l=x;
for (int i=1;i<=n-1;i++)
for (int j=i+1;j<=n;j++)
{
k=l;
int al,b;
if (c[j]>c[i]) al=c[j]-c[i],b=a[i]-a[j];
else al=c[i]-c[j],b=a[j]-a[i];
int t=gcd(al,k);
if (b%t) continue;
al/=t; b/=t; k/=t;
fx=fy=0;
exgcd(al,k); //cout<<fx<<" "<<b<<" "<<k<<endl;
fx=(fx%k*b%k+k)%k; //cout<<fx<<endl;
if (fx<=min(p[i],p[j])) return false;
}
return true;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d%d%d",&a[i],&c[i],&p[i]),maxn=max(maxn,a[i]);
for (int i=maxn;i<=1000000;i++)
if (work(i))
{
printf("%d\n",i);
return 0;
}
}