bzoj 1407: [Noi2002]Savage

1407: [Noi2002]Savage

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 1234   Solved: 559
[ Submit][ Status][ Discuss]

Description

bzoj 1407: [Noi2002]Savage_第1张图片

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

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

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




你可能感兴趣的:(bzoj 1407: [Noi2002]Savage)