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 }
    解方程
  • 相关阅读:
    【Asp.Net从零开始】:上传文件(FileUpload)
    JavaScript变量声明及赋值
    427 类型数据
    427 自适应量化
    428 x264_reference_update
    427 expand_border
    426 pixel赋值问题 mbcmp函数 宏定义
    427 mb中一些参数记录备忘
    427 参考帧管理
    427 参数原来还有很多没有理解 比较详细的解释
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7363021.html
Copyright © 2011-2022 走看看