1. 程式人生 > >【bzoj2048】[2009國家集訓隊]書堆 數論

【bzoj2048】[2009國家集訓隊]書堆 數論

font 大整數 src class jpg ppr %d logs 條件

題目描述

技術分享

輸入

第一行正整數 N M

輸出

一行(有換行符),L,表示水平延伸最遠的整數距離 (不大於答案的最大整數)

樣例

#1
Input: 1 100
Output: 49
#2
Input: 2 100
Output: 74


題解

數論

一個結論:桌面上擺$n$本長度為$l$的書,不掉出桌面,能夠伸出桌面的最大長度為$\frac 12l*H_n$,其中$H_n=\sum\limits_{i=1}^n\frac 1i$。

證明:設i本書按該條件擺放,它們的重心距離最下面的書的邊緣的距離為$\frac12l*f(i)$,那麽首先有$f(1)=1$,而考慮$i$本書的情況,上面的$i-1$本的重心一定是在第$i$本的邊緣上。那麽由杠桿原理,$(i-1)*f(i)=1*(1-f(i))$可知,故$f(i)=\frac 1i$。而每次都是重心落在邊緣,所以伸出長度即為每次的重心與邊緣的距離之和$H_n$。

但是$n$有$10^18$之大,直接暴力肯定使不可取的。考慮調和級數的近似值:$H_n\approx ln(n+1)+\gamma$,其中$\gamma$為歐拉常數,它約為0.57721566490153286060651209。

這個公式當$n$較小時誤差較大,所以當$n$較小時考慮暴力求解,$n$較大時套用公式。

#include <cmath>
#include <cstdio>
typedef long long ll;
int main()
{
	ll n , m , i;
	double ans = 0;
	scanf("%lld%lld" , &n , &m);
	if(n <= 1000000)
		for(i = 1 ; i <= n ; i ++ )
			ans += 0.5 / i;
	else ans = 0.5 * (log(n + 1) + 0.5772156649);
	ans *= m;
	printf("%d\n" , (int)(ans - 1e-9));
	return 0;
}

【bzoj2048】[2009國家集訓隊]書堆 數論