bzoj 1407 [Noi2002]Savage

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1407

因为答案有很小的限制,所以可以枚举。(听说不能二分?)

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

<==>T*(p[ i ] - p[ j ]) + k * m = c[ j ] - c[ i ]

然后需要打一个正确的板子。

放一点笔记:

exgcd有解,仅当得数是gcd的倍数。这样可以求出特解后同乘一个数得到解。
ax+by=c的通解:ax1+by1=c;ax2+by2=c;  ->  a(x1-x2)+b(y1-y2)=0;  ->  a*del(x)+b*del(y)=0
        把a和b都除以它们的gcd,得a0*del(x)+b0*del(y)=0;
        因为互质,所以最小的del(x)=-b0 , del(y)=a0。

特别奇怪的是如果不判 if (b<0) b = -b 就会WA。可是b什么时候会变成负数呢?

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=20,M=1e6;
int n,m,c[N],p[N],l[N],x,y;
bool flag;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
void exgcd(int a,int b)
{
    if(!b){x=1;y=0;return;}
    exgcd(b,a%b);
    int tx=x;
    x=y;y=tx-a/b*y;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d%d",&c[i],&p[i],&l[i]),m=max(m,c[i]);//
    for(;m<=M;m++)
    {
        flag=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int a=p[i]-p[j],b=m,w=c[j]-c[i],g=gcd(a,b);
                if(w%g)continue;
                a/=g;b/=g;w/=g;//
                if(b<0)b=-b;    //
                exgcd(a,b);
                x=(x*w%b+b)%b;//*w,解出来的东西对应得数是gcd,现在约了g,gcd=1,故同乘w
                if(x<=min(l[i],l[j])){flag=1;break;}
            }
            if(flag)break;
        }
        if(!flag)
        {
            printf("%d",m);return 0;
        }
    }
}

原文地址:https://www.cnblogs.com/Narh/p/9251433.html

时间: 2024-10-11 00:27:02

bzoj 1407 [Noi2002]Savage的相关文章

BZOJ 1407: [Noi2002]Savage( 数论 )

枚举答案, 然后O(N^2)枚举野人去判他们是否会在有生之年存在同山洞. 具体做法就是: 设第x年相遇, 则 Ci+x*Pi=Cj+x*Pj (mod M), 然后解同余方程. 复杂度应该是O(ans*N^2log(ans)), 但是实际远小于....能够AC -------------------------------------------------------------------- #include<cstdio> #include<algorithm> #inclu

【BZOJ 1407】[Noi2002]Savage ExGCD

我bitset+二分未遂后就来用ExGCD了,然而这道题的时间复杂度还真是玄学...... 我们枚举m然后对每一对用ExGCD判解,我们只要满足在最小的一方死亡之前无解就可以了,对于怎么用,就是ax+by=c,在这里c是距离差,a是速度差,b是m,x是我们要的解,y随意. 时间复杂度O(m*n*n*log),然而这是标解.......... #include <cstdio> int prob[120][3],len,n,c[16],p[16],l[16],S; inline int Min(

BZOJ 1407 Savage(拓展欧几里得)

这题的时间复杂度真玄学... O(m*n^2).1e8也能过啊... 首先题目保证m<=1e6. 这启发我们枚举或者二分答案? 但是答案不满足单调性,考虑从小到大枚举m. 对于每一个m,枚举两个野人在有生之年能否住在一起.可以推出一个同余方程,用扩欧可以求出最小整数解x,或者没有解. 如果x<=life[i]&&x<=life[j]那么当然不满足条件. # include <cstdio> # include <cstring> # include

BZOJ 1407 Savage

怎么枚举下答案就过了.... 以后exgcd还是这么写比较稳当. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #define maxn 20 using namespace std; int n,c[maxn],p[maxn],l[maxn],mx=0,x,y; int gcd(int a,int b) {

[BZOJ1407][NOI2002]Savage(扩展欧几里德)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1407 分析: m,n范围都不大,所以可以考虑枚举 先枚举m,然后判定某个m行不行 某个m可以作为一个解当且仅当: 对于任意的i,j 模方程:c[i]+x*p[i]=c[j]+x*p[j] (mod m) 无解或者最小正整数解>min(l[i],l[j]) 这个可以用扩展欧几里德解决. 因为n<=15,所以可以暴力枚举每对i,j

BZOJ 1408: [Noi2002]Robot

1408: [Noi2002]Robot Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 510  Solved: 344[Submit][Status][Discuss] Description Input Output Sample Input 3 2 1 3 2 5 1 Sample Output 8 6 75 HINT 90号机器人有10个老师,加上它自己共11个.其中政客只有15号:军人有3号和5号:学者有8个,它们的编号分别是:2,6,9,

bzoj1407 [Noi2002]Savage

Description Input 第1行为一个整数N(1<=N<=15),即野人的数目. 第2行到第N+1每行为三个整数Ci, Pi, Li表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值. (1<=Ci,Pi<=100, 0<=Li<=10^6 ) Output 仅包含一个数M,即最少可能的山洞数.输入数据保证有解,且M不大于10^6. Sample Input 3 1 3 4 2 7 3 3 2 1 Sample Output 6 //该样例对应于题目描述

bzoj1407 [Noi2002]Savage——扩展欧几里得

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1407 看到一定有解,而且小于10^6,所以可以枚举: 判断一个解是否可行,就两两判断野人 i , j 能否满足在寿命内不相遇: 也就是 T*pi + ci ≡ T*pj + cj (mod m) 变成  ( pi - pj )*T + km = cj - ci 用扩展欧几里得解这个方程,得到T若大于两人中较小的寿命或无解则可行. 代码如下: #include<iostream> #inc

bzoj 1407

裸最大权封闭子图 1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(int i=l;i<=r;i++) 3 #define dec(i,l,r) for(int i=l;i>=r;i--) 4 #define link(x) for(edge *j=h[x];j;j=j->next) 5 #define mem(a) memset(a,0,sizeof(a)) 6 #define inf 1e9 7 #define ll l