题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1407
比赛的时候写这题我写了个瞎二分,然后最后半个小时发现不满足二分性质,就又随性的加上了枚举,于是...得到了20分的安慰分
好吧其实正解就是枚举,我们从小到大枚举山洞的个数
怎么判断是否会有野人相遇呢?若有m个山洞,对于野人i,j,他们相遇的充要条件就是:
Ci+xPi≡Cj+xPj (mod m)
移项可得:Ci-Cj≡x(Pj-Pi) (mod m)
于是我们设 x(Pj-Pi)+ym=Ci-Cj
设A=Pj-Pi B=m C=Ci-Cj,考虑解不定方程Ax+By=C
对于x的最小正整数解,若满足x<=min(L[i],L[j]),那么两个野人就可以在有生之年相遇
既然这样,我们依次枚举两个野人就好
怎么解不定方程...就不说了
#include<cstdio> #include<algorithm> using namespace std; const int maxn=25; int n,minc; int c[maxn],p[maxn],l[maxn]; int gcd(int x,int y) {if (x%y==0) return y;else return gcd(y,x%y);} void exgcd(int A,int B,int &x,int &y) { if (!B) { x=1;y=0;return; } exgcd(B,A%B,x,y); int z=x;x=y;y=z-y*(A/B); } bool check(int t) { for (int i=1;i<=n;i++) { for (int j=i+1;j<=n;j++) { int A=p[i]-p[j],B=t,C=c[j]-c[i],x,y; int gg=gcd(A,B); if (C%gg==0) { A/=gg;B/=gg;C/=gg; exgcd(A,B,x,y); B=abs(B); x=((x*C)%B+B)%B; while (!x) x+=B; if (x<=min(l[i],l[j])) return 0; } } } return 1; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d%d%d",c+i,p+i,l+i); minc=max(minc,c[i]); } for (int t=minc;;t++) if (check(t)) {printf("%d",t);break;} return 0; }