加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-14 04:22:23 所属栏目:大数据 来源:网络整理
导读:题意与分析 二分题。考虑到n的范围是 (10^{12}) ,注意到等比公式 (S=a_1frac{1-q^n}{1-q} (qne 1)) ,可以看出,不论q有多大(1除外,这个时候 (r=1,k=n) ),你再怎么大q(也就是r)不会大过64(甚至可以更小)。 因此,穷举r,二分查找k即可。算k

题意与分析

二分题。考虑到n的范围是(10^{12}),注意到等比公式(S=a_1frac{1-q^n}{1-q} (qne 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 %lldn",ansk);
    }
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读