题解 CF760B

题解 CF760B

考虑二分 \(k\) 位置的枕头个数 \(x\) ,因为相邻的位置枕头个数与当前位置个数差不能大于 \(1\) ,所以考虑通过当前位置枕头个数来求出 \(n\) 个位置上枕头个数的总和,可以考虑分为 \([1,i),[i,k),[k,j),(j,n]\) 四个区间,其中第一个和最后一个区间为每个位置枕头数都为 \(1\) 的区间,第二个区间的值域为 \([1,x)\) 第三个区间的值域为 \([x,1]\)

因为第二三个区间如图规律,所以很容易得出:第二个区间长度为 \(len=x-1\) ,第三个区间长度为 \(ren=x\)

!! 若第二三个区间不完整,则没有第一四个区间,二三区间长度分别为 \(\min(len,k-1),\min(n-k+1,ren)\)

考虑怎么统计:

  1. 第一个区间总和很明显为 \(k-1-len\)
  2. 第四个区间总和为 \(n-(k+ren-1)\)
  3. 第二个区间和为

\[(x-1)+(x-2)+\dots +(x-len) \]

\[\sum_{1}^{len}x-1-2-\dots -len \]

\[\sum_{1}^{len}x-(1+2+\dots +len) \]

\[\sum_{1}^{len}x-\frac{len\times(1+len)}{2} \]

\[len\times x-\frac{len+len^2}{2} \]

  1. 第三个区间和为

\[x+(x-1)+(x-2)+\dots+(x-(ren-1)) \]

\[\sum_{1}^{ren}x-0-1-2-\dots -(ren-1) \]

\[\sum_{1}^{ren}x-(0+1+2+\dots +(ren-1)) \]

\[\sum_{1}^{ren}x-\frac{ren\times(0+ren-1)}{2} \]

\[ren\times x-\frac{ren^2-ren}{2} \]

以上所有总和为当 \(k\) 位置有 \(x\) 个枕头时,总的枕头数,若大于给定 \(m\) ,则需要调小数值,小于则反之。

#include<cstdio>
#include<vector>
#include<cstring>
#define int long long
using namespace std;
template<typename T>T read(T &x){char c=getchar();x=0;T f=1;for(;c<'0' || c>'9';c=getchar())if(c=='-') f=~f+1;for(;c>='0' &&c<='9';c=getchar()) x=(x<<3)+(x<<1)+(c^'0');return x=x*f;}
template<typename T,typename...T2>void read(T &x,T2 &...y){read(x);read(y...);return;}

int n,m,k;

bool check(int x){
	int len=x-1,ren=x;
	len=min(len,k-1),ren=min(ren,n-k+1);
	int sum=x*len-(len+len*len)/2+k-len-1+ren*x-(ren*ren-ren)/2+n-(k+ren-1);
	if(sum>m) return 0;
	return 1;
}

signed main(){
	read(n,m,k);
	int l=1,r=m+1;
	while(l<r){
		int mid=(l+r)>>1;
		if(check(mid)) l=mid+1;
		else r=mid;
	}
	printf("%lld",l-1);
	return 0;
}
posted @ 2024-01-30 13:37  Tyrue  阅读(4)  评论(0编辑  收藏  举报