zoukankan      html  css  js  c++  java
  • P2421 [NOI2002]荒岛野人

    题目链接

    暴力非常好写,按题目模拟即可。这样经过测试有40分。

    正解做法:

    题目上的条件可以转化为找一个山洞数,使下面的式子无解。

    接着移项,可以变为

     典型的同余方程,然后因为题目中的n极小,所以可以n^2暴力判断。

    枚举的时候注意初始值为c[i]的最大值,然后枚举判断,无解的情况有两种:

    1.在有生之年内都不会在一个山洞中,也就是该方程的最小正整数解>t值。

    2.本来这个方程就无解。

    还有,求得的gcd可能为负值,要变为相反数再求解最小正整数解。

    代码(40分暴力):

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    int n;
    int save[maxn],c[maxn],p[maxn],t[maxn],life[maxn];
    int maxx;
    int tot;
    bool flag;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&c[i],&p[i],&t[i]);
            maxx=max(c[i],maxx);
            life[i]=t[i];
            save[i]=c[i];
        }
        for(int i=maxx;;i++){
            flag=false;
            tot=0;
            memcpy(c,save,sizeof(c));
            memcpy(t,life,sizeof(t));
            while(1){
                for(int j=1;j<=n;j++){
                    int save=c[j];
                    if(t[j]>0){
                        c[j]+=p[j];    
                        if(c[j]>i) c[j]%=i;
                        if(!c[j]) c[j]=save;
                    }  
                }
                for(int j=1;j<=n;j++){
                    for(int k=j+1;k<=n;k++){
                        if(c[j]==c[k]&&t[j]>0&&t[k]>0){
                            flag=true;
                            break;
                        } 
                    }
                }
                for(int j=1;j<=n;j++) t[j]--;
                for(int j=1;j<=n;j++) if(!t[j]) tot++;
                if(flag||tot==n) break;
             }
             if(!flag){
                 printf("%d
    ",i);
                 return 0;
            }
        }
        return 0;
    }
    View Code

    正解(exgcd):

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    int n;
    int c[maxn],p[maxn],t[maxn];
    long long x,y;
    int maxx;
    long long exgcd(long long a,long long &x,long long b,long long &y){
        if(!b){
            x=1;
            y=0;
            return a;
        }
        long long gcd=exgcd(b,x,a%b,y);
        long long tmp=x;
        x=y;
        y=tmp-(a/b)*x;
        return gcd;
    }
    bool check(long long ans){
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                long long a=p[i]-p[j],b=ans,cc=c[j]-c[i];
                long long gcd=exgcd(a,x,b,y);
                if(cc%gcd) continue;
                if(b/gcd<0) b=-b;//注意有负数的情况 
                x=((x*cc/gcd)%(b/gcd)+(b/gcd))%(b/gcd);
                if(x<=t[i]&&x<=t[j]) return false;
            }
        }
        return true;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&c[i],&p[i],&t[i]);
            maxx=max(c[i],maxx);
        } 
        for(int i=maxx;;i++){
            if(check(i)){
                printf("%d
    ",i);
                return 0;
            }
        } 
         return 0;
    } 
    View Code

     

  • 相关阅读:
    Jenkins的安全控制
    浅谈JNDI的使用
    hdu 4544 湫湫系列故事——消灭兔子
    如何在工作和实践中学习射频知识
    JSONObject 解析
    SharePoint 2010 WebPart Web部分 总的膏
    J2EE学习笔记
    C和指针 (pointers on C)——第十二章:利用结构和指针
    UVA
    EasyUI-DataGrid多线动态实现选择性合并
  • 原文地址:https://www.cnblogs.com/LJB666/p/11695421.html
Copyright © 2011-2022 走看看