Yukari's Birthday HDU

来源:互联网 发布:域名注册购买 编辑:程序博客网 时间:2024/05/20 12:22

题目描述:给定一个数n,求满足k + k^2 + k^3 + ... + k^r = n 或 n - 1的k和r值,并且k*r结果最小,若有多组符合要求的k 、r,取r最小的。

思路:我一开始想的是r比较好用k表示出来,所以应该可以直接二分枚举k的值,根据n 、k得出r的值,若r为整数则该组k r符合要求,求出最小的。但是学弟说k的值可能很大(最大为n-1),但是r的值就很小了,最大不超过38,所以可以一次枚举r的值,二分求出对应的k,记录最优解。的确二分r才是明智的想法。

反思:不算难得一道题,训练赛时想到了二分但是一开始想错了对象。赛后补题时想当然将k初值设为inf结果发现这里n最大为1e12,所以k的值可能比我设的inf还大,所以导致一直wa。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#include<cstdlib>#include<sstream>#include<deque>#include<stack>#include<set>#include<map>using namespace std;typedef long long ll;typedef unsigned long long ull;const double eps = 1e-6;const int maxn = 30;const int maxt = 1e6 + 10;const int mod = 10000007;const int dx[] = {1, -1, 0, 0, -1, -1, 1, 1};const int dy[] = {0, 0, -1, 1, -1, 1, -1, 1};const int Dis[] = {-1, 1, -5, 5};const ll inf = 0x3f3f3f3f;ll n, k;int r;int check(ll cntk, int cntr){    ll ans = cntk;    ll tmp = cntk;    for(int i = 2; i <= cntr; ++i){        tmp *= cntk;        ans += tmp;        if(ans > n) return 1;    }    if(ans == n || ans == n - 1) return 0;    if(ans < n - 1) return -1;    return 1;}int main(){    while(~scanf("%I64d", &n)){        r = 100;        k = n;//k的初值要足够大。        for(int rr = 2; rr <= 40; ++rr){//枚举r,二分找出对应的k值            ll low = 2, high = (ll)pow(n + 1, 1.0 / rr) + 2, mid;//注意k的上界范围。            int cnt;            while(low <= high){                mid = low + (high - low) / 2;                cnt = check(mid, rr);                if(cnt == 0){                    if((rr * mid < r * k) || (rr * mid == r * k && rr < r)){                        r = rr; k = mid;                    }                    break;                }                else if(cnt == 1){                    high = mid - 1;                }                else{                    low = mid + 1;                }            }        }        if((ll)r * k > n - 1){            r = 1; k = n - 1;        }        printf("%d %I64d\n", r, k);    }    return 0;}




原创粉丝点击