zoukankan      html  css  js  c++  java
  • [NOI2002] 荒岛野人 扩展欧几里得算法

    【问题描述】

    克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞 C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。每个野人i有一个寿命值Li,即生存的年数。下面四幅图描述了一个有6个 山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴编号依次为1,2,3;每年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。

    Image:Savage1.gif Image:Savage2.gif

    Image:Savage3.gif Image:Savage4.gif

    奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?


    【输入文件】

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


    【输出文件】

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

    solution

    (其实这个题根据 M不大于10^6 知道要枚举M)


    我一开始思路是:

    设当前总共的洞穴数是m个

    对于每两个野人,如果他们会相遇,那么会有

    (C[i]+k*P[i])≡(C[j]+k*P[j]) (%m)

    即 m*t1=C[i]+k*P[i]...①  m*t2=C[j]+k*P[j]...②

    ①+②得   m*(t1+t2)-(P[i]+P[j])*k=C[i]+C[j]

    可是这样没法解方程,就放弃了


    看题解是:

    对于野人i   (C[i]+k*P[i])%m=S1→C[i]+k*P[i]-k1*m=S1

    对于野人j   (C[j]+k*P[j])%m=S2→C[j]+k*P[j]-k2*m=S2

    相遇的条件是 S1==S2

    所以两式相减  (P[i]-P[j])*k+x*m=C[j]-C[i]   (此时野人相遇S1==S2)

    最后如果方程 无解 OR k>L[i]||k>L[j]  即为不相遇

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<iostream>
     4 #include<cstdlib>
     5 #define ll long long
     6 #define dd double
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 using namespace std;
     9 inline int maxn(int a,int b){return a>b?a:b;}
    10 int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
    11 
    12 int n,be;
    13 int C[21],p[21],L[21];
    14 
    15 void egcd(int a,int b,int &x,int &y)
    16 {
    17     if(b==0)
    18     {
    19         x=1;
    20         y=0;
    21         return ;
    22     }
    23     egcd(b,a%b,x,y);
    24     int temp=x;
    25     x=y;
    26     y=temp-a/b*y;
    27 }
    28 
    29 int check(int now)
    30 {
    31     int x,y,d,a,b,c;
    32     for(int i=1;i<=n;++i)
    33       for(int j=i+1;j<=n;++j)
    34       {
    35             a=p[i]-p[j];
    36             b=now;
    37             c=C[j]-C[i];
    38             d=gcd(a,b);
    39             
    40             if(c%d!=0)
    41               continue;
    42             a/=d;
    43             b/=d;
    44             c/=d;
    45             egcd(a,b,x,y);
    46             b=abs(b);
    47             x=((x*c)%b+b)%b;
    48             if(x==0)
    49               x+=b;
    50             if(x<=min(L[i],L[j]))
    51               return 0;
    52         }
    53     return 1;
    54 }
    55 
    56 int main(){
    57     
    58     //freopen("savage.in","r",stdin);
    59     //freopen("savage.out","w",stdout);
    60     
    61     //freopen("1.txt","r",stdin);
    62     
    63     scanf("%d",&n);
    64     for(int i=1;i<=n;++i)
    65     {
    66       scanf("%d%d%d",&C[i],&p[i],&L[i]);
    67         be=maxn(be,C[i]);
    68     }
    69     for(int i=be;i<=1000000;++i)
    70       if(check(i))
    71       {
    72             cout<<i;
    73             break;
    74         }
    75     //while(1);
    76     return 0;
    77 }
    code

     最后再复习一下扩展欧几里得算法:

    对于 ax+by=c

    1.如果 c%gcd!=0,无解

    2.求出gcd=gcd(a,b)   a/=gcd  b/=gcd  c/=gcd  先约分

    3.egcd 解方程

    4.x*c   y*c   是此方程一组解

    5.如果要 求x,那么b=abs(b),x=x0+b*t(b已经约分,不用再/gcd)

      求y也一样

    6.

    int a,b;

    a>0,b<0

    此时a%b,应该是b先=abs(b),a再%b.....

     1 int gcd(int x,int y)
     2 {
     3     return y==0?x:gcd(y,x%y);
     4 }
     5 
     6 void egcd(int a,int b,int &x,int &y)
     7 {
     8     if(b==0)
     9     {
    10         x=1;
    11         y=0
    12         return ;
    13     }
    14     int temp=x;
    15     x=y;
    16     y=temp-a/b*y;
    17 }
    18 
    19 int cal(int a,int b,int c)
    20 {
    21     int x,y,d;
    22     d=gcd(a,b);
    23     if(c%d)
    24       return -1;
    25     a/=d;b/=d;c/=d;
    26     egcd(a,b,x,y);
    27     x=((c*x)%b+b)%b;
    28     if(x==0)x+=b;
    29     return x;
    30 }
    解方程
  • 相关阅读:
    【Codechef】Chef and Bike(二维多项式插值)
    USACO 完结的一些感想
    USACO 6.5 Checker Challenge
    USACO 6.5 The Clocks
    USACO 6.5 Betsy's Tour (插头dp)
    USACO 6.5 Closed Fences
    USACO 6.4 Electric Fences
    USACO 6.5 All Latin Squares
    USACO 6.4 The Primes
    USACO 6.4 Wisconsin Squares
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7363021.html
Copyright © 2011-2022 走看看