膜 社论(egg drop)

题面

nm 个鸡蛋,从 k 楼及以上扔下去会碎,不能再测试 .

问至少需要扔几次确定 k .

n1018m64 .

题解

dpi,j 表示 i 个鸡蛋丢 j 次能确定的最高楼层(其实是 OEIS A180975 / A131251) .

显然最后一个走第 k 步的时候,和上一步之间的空隙不能超过 dpi1,jk+1,不然中间无法判定 .

于是

dpi,j=k=1j(dpi1,jk+1)=j+k=0j1dpi1,k=dpi1,j+dpi1,j1+1

dpi,j=dpi1,j+dpi1,j1+1 .

我们转成一个二项式系数的形式:

dpi,j=p=0j1q=0i1(pq)

过程(artalter)

gi,j=dpi+1,jdpi,j .

gi,j=(1+dpi,j+dpi,j1)(1+dpi1,j+dpi1,j1)=dpi,j+dpi,j1dpi1,jdpi1,j1=(dpi,jdpi1,j)+(dpi,j1dpi1,j1)=gi1,j+gi1,j1

妈呀这不是组合数吗?

于是就可以轻易建立 dpg 的联系,从而推出式子了 .

随便推推

dpi,j=p=0j1q=0i1(pq)=q=0i1p=0j1(pq)=q=0i1(jq+1)

然后随便线性做了 .

外面套一个二分就完了 .

时间复杂度 O(mlogn) .


细节:dp 增长很快,大于 n 直接丢掉,用 double 注意浮点误差

代码

using namespace std;
typedef long long ll;
typedef __int128 i128;
const int N = 111;
const double LIM = 1e18;
ll n, k;
inline bool check(ll x)
{
	i128 now=1, ans=0;
	for (int l=0; l<k; l++)
	{
		if (1.0*now*(x-l)/(l+1) > LIM) return true;
		now = now*(x-l)/(l+1); ans += now;
		if (ans >= n) return true;
	} return ans >= n;
}
int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		scanf("%lld%lld", &n, &k);
		ll l=0, r=n, ans=-1;
		while (l <= r)
		{
			ll mid = (l + r) >> 1;
			if (check(mid)){r = mid-1; ans = mid;}
			else l = mid+1;
		}
		printf("%lld\n", ans);
	}
	return 0;
}
posted @   yspm  阅读(152)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2020-02-12 浅谈排序算法[动图]
😅​
点击右上角即可分享
微信分享提示