题目
https://www.luogu.com.cn/problem/P5425
思路
又是喜闻乐见的二分答案题,那么关键就是check函数的编写了。
我们考虑每次枚举一个(mid),然后判断是否存在一种分配方案使所有不同组奶牛之间的距离都(geq mid)
对于这个距离((2019201913x+2019201949y) mod 2019201997),根据同余性质,直接变成(-84*x-48*y),又:(Nleq 7500),所以距离很小,之后这个取模就没用了。
同时,根据式子,发现x和y越大,不满足条件的可能性就越大。
对于(n)号奶牛,我们看哪些可以和它分到不同组,哪些必须和它分到同一组。根据式子单调性可以发现,必须和它分到同一组的奶牛必然是(n-1,n-2,...,n-t)这样连续的一段。
同时,既然(n-t-1)号可以和(n)号分开,那它也必然可以和(n-1,n-2,...n-t)号分开,所以处理完(n)号就直接去处理(n-t-1)号,每头奶牛只访问一次,所以check函数是O(n)的。
总体时间复杂度为(nlog2019201997),可以承受。
代码
#include<cstdlib>
#define mod 2019201997
#define ll long long
using namespace std;
int n,m;
ll f(int x,int y){
return -84*x-48*y;
}
int check(ll x){
int i=n,cnt=0,j=1;
while(i>=1){
j=i-1;
while(j>=1&&f(j,i)<x){
j--;
}
cnt++;
i=j;
}
if(cnt>=m) return 1;
else return 0;
}
int main(){
int i,j;
ll l=-mod,r=-1;
scanf("%d%d",&n,&m);
while(l<r){
ll mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%lld",mod+l);
// system("pause");
return 0;
}