1. 程式人生 > >[BZOJ 1407] Savage

[BZOJ 1407] Savage

element i++ 發生 bool ava -s 人在 c++ 轉變

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

Solution:

由於此題裏n的範圍很小,因此可以直接從小到大枚舉m(O(m*n^2))

那麽問題轉變為一個判定性問題:已知m,問所有野人在它們的有生之年裏是否會出現沖突

由於O(m*n^2)的復雜度符合要求,枚舉每一對(i,j)是否會發生沖突即可

可將問題轉化為求次同余式中最小的x

\[(step_i-step_j)x\equiv pos_j-pos_i(\mod m)\]

接下來就是數論裏的套路了:

ax≡b(mod c)可以轉化為求ax+cy=b,我們可以用擴展歐幾裏得求出x,y值,同時順便求出GCD。

設k=c/GCD(a,c),

那麽方程ax≡b(mod c)的一個特解:x0=x*(b/GCD(a,c))%c。(如果b不是GCD(a,c)的倍數則無解)

並且它的GCD(a,c)個解分別為:xi=(x0+i*(k))%c,{i=0,1,2,.....GCD(a,c)-1}。

方程ax≡b(mod c)的最小解為:(x0%k+k)%k。

Code:

#include <bits/stdc++.h>

using namespace std;
const int MAXN=20;

int n,c[MAXN],p[MAXN],l[MAXN];

int exgcd(int a,int b,int
&x,int &y) { if(!b){x=1;y=0;return a;} int ret=exgcd(b,a%b,x,y),t=x; x=y;y=t-a/b*y;return ret; } bool check(int m) { for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) { int A=p[i]-p[j],B=c[j]-c[i],x,y,GCD=exgcd(A,m,x,y); if(B%GCD) continue
; x=((x*B/GCD)%(m/GCD)+abs(m/GCD))%(m/GCD); if(x<=min(l[i],l[j])) return false; } return true; } int main() { cin >> n;int mx=0; for(int i=1;i<=n;i++) cin >> c[i] >> p[i] >> l[i],mx=max(mx,c[i]); for(int i=mx;i<=1e6;i++) if(check(i)) return cout << i,0; return 0; }

[BZOJ 1407] Savage