「日常训练」 Yukari's Birthday(ZOJ-3665)

题意与分析

二分题。考虑到n的范围是(10^{12}),注意到等比公式(S=a_1frac{1-q^n}{1-q} (q e 1)),可以看出,不论q有多大(1除外,这个时候(r=1,k=n)),你再怎么大q(也就是r)不会大过64(甚至可以更小)。
因此,穷举r,二分查找k即可。算k的时候完全可以老老实实的一步一步循环,因为这样不容易溢出,反而少了很多麻烦。

代码

#include <bits/stdc++.h>

#define rep(i,a,b) for(repType i=(a);i<=(b);++i)
using namespace std;
typedef long long ll;
typedef int repType;
double logn;
ll n,ansr,ansk;
void solve(ll d, ll up, int r)
{
	ll sum=0;
	while(d<up)
	{
		ll mid=d+(up-d)/2;
		sum=0;
		ll know=1;
		bool flag=false;
		rep(i,1,r)
		{
			know*=mid;
			sum+=know;
			if(sum>=1e12 || sum<0)
			{
				flag=true;
				break;
			}
		}
		if(flag) { up=mid; continue; } // overflow, get smaller
		if(sum>n) up=mid;
		else d=mid+1;
		if(sum+1 == n || sum == n) 
		{
			if(mid*r<ansr*ansk)
			{
				ansr=r;
				ansk=mid;
				break;
			}
		}
	}
}

int main()
{
	while(~scanf("%lld",&n))
	{
		ansr=1; ansk=n-1;
		rep(i,2,64)
			solve(1ll,1e6,i);
		printf("%lld %lld
", ansr,ansk);
	}
	return 0;
}
如非注明,原创内容遵循GFDLv1.3发布;其中的代码遵循GPLv3发布。
原文地址:https://www.cnblogs.com/samhx/p/zoj-3665.html