bzoj 1407 //1407: [Noi2002]Savage 扩展欧几里得

bzoj 1407   //1407: [Noi2002]Savage   扩展欧几里得

bzoj 1407   //1407: [Noi2002]Savage   //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1407
//在线测评地址https://www.luogu.org/problem/P2421

更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录

Accepted 820 kb 1032 ms C++/Edit 1336 B

//1407: [Noi2002]Savage
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1407
//在线测评地址https://www.luogu.org/problem/P2421
//题意清晰,怎么做呢。2019-11-17 13:57
//青蛙的约会,有2只青蛙,该题野人最多能到15个。
//此文http://hzwer.com/3297.html思路写得不错,摘抄如下
/*
枚举m>=max{c[i]}

使得对于每一对i,j

有c[i]+x*p[i]=c[j]+x*p[j] (mod m)

无解或者最小正整数解>min(l[i],l[j])

上式可以用exgcd求解

即(p[i]-p[j])*x-my=c[j]-c[i]
*/
//看了上述思路,想了想,枚举m确实没想到,野人两两比较想到了,却没敢去试。2019-11-17 14:56
//编写过程中,发现一个比较重大的错误,错误代码如下
/*
x=(x%b+b)%b;//保证x>=0
if(!x)x=b;//x=0要注意
x*=C;
应改成
x*=C;
x=(x%b+b)%b;//保证x>=0
if(!x)x=b;//x=0要注意
*/
//a=p[i]-p[j],b=m,C=c[j]-c[i];//此处错写成a=myabs(p[i]-p[j]),b=m,C=myabs(c[i]-c[j]);
//样例通过,提交Time_Limit_Exceed    816 kb    5000 ms    C++/Edit    1161 B。2019-11-17 17:13
//该题有坑,存在d<0,导致b<0的情况
//b=myabs(b);//漏了该句,该题有坑,存在d<0,导致b<0的情况
//样例通过,提交AC。2019-11-17 17:23
#include
#define maxn 20
int c[maxn],p[maxn],l[maxn],n;
int myabs(int a){
    return a>=0?a:-a;
}
int max(int a,int b){
    return a>b?a:b;
}
int min(int a,int b){
    return a }
int gcd(int a,int b){
    return b?gcd(b,a%b):a;//此处错写成return b?a:gcd(b,a%b);
}
void exgcd(int a,int b,int *x,int *y){
    int t;
    if(b==0){
        *x=1,*y=0;
        return ;
    }
    exgcd(b,a%b,x,y);
    t=*x,*x=*y,*y=t-a/b**y;//此处错写成t=*x,*x=*x-a/b**y,*y=t;
}
int judge(int m){
    int i,j,a,b,C,d,x,y;//x延续年数
    for(i=1;i<=n;i++)
        for(j=i+1;j<=n;j++){
            a=p[i]-p[j],b=m,C=c[j]-c[i];//此处错写成a=myabs(p[i]-p[j]),b=m,C=myabs(c[i]-c[j]);
            d=gcd(a,b);
            if(C%d)continue;//无解。
            a/=d,b/=d,C/=d;//该题有坑,存在d<0,导致b<0的情况
            exgcd(a,b,&x,&y);
            x*=C;//写错顺序,要出问题。
            b=myabs(b);//漏了该句,该题有坑,存在d<0,导致b<0的情况
            x=(x%b+b)%b;//保证x>=0
            if(!x)x=b;//x=0要注意
            if(x<=min(l[i],l[j]))return 0;
        }
    return 1;
}
int main(){
    int i,j,mx=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d%d%d",&c[i],&p[i],&l[i]),mx=max(mx,c[i]);
    for(i=mx;;i++)
        if(judge(i)){
            printf("%d\n",i);
            return 0;
        }
}

模仿洛谷P1516 青蛙的约会https://www.luogu.org/problem/P1516写的代码

Accepted 820 kb 1396 ms C++/Edit 1188 B

#include
#define maxn 20
int c[maxn],p[maxn],l[maxn],n;
int max(int a,int b){
    return a>b?a:b;
}
int min(int a,int b){
    return a }
int gcd(int a,int b){
    return b?gcd(b,a%b):a;//此处错写成return b?a:gcd(b,a%b);
}
void exgcd(int a,int b,int *x,int *y){
    int t;
    if(b==0){
        *x=1,*y=0;
        return ;
    }
    exgcd(b,a%b,x,y);
    t=*x,*x=*y,*y=t-a/b**y;//此处错写成t=*x,*x=*x-a/b**y,*y=t;
}
int judge(int m){
    int i,j,a,b,C,d,x,y;//x延续年数
    for(i=1;i<=n;i++)
        for(j=i+1;j<=n;j++){
            a=p[i]-p[j],b=m,C=c[j]-c[i];//此处错写成a=myabs(p[i]-p[j]),b=m,C=myabs(c[i]-c[j]);
            a=(a%m+m)%m,C=(C%m+m)%m;
            d=gcd(a,b);
            if(C%d)continue;//无解。
            a/=d,b/=d,C/=d;
            exgcd(a,b,&x,&y);
            x*=C;//写错顺序,要出问题。
            x=(x%b+b)%b;//保证x>=0
            if(!x)x=b;//x=0要注意
            if(x<=min(l[i],l[j]))return 0;
        }
    return 1;
}
int main(){
    int i,j,mx=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d%d%d",&c[i],&p[i],&l[i]),mx=max(mx,c[i]);
    for(i=mx;;i++)
        if(judge(i)){
            printf("%d\n",i);
            return 0;
        }
}

 

你可能感兴趣的:(跟着大佬学算法)