D题 Codeforces 325B Stadium And Games

来源:互联网 发布:飞利浦剃须刀淘宝店 编辑:程序博客网 时间:2024/06/05 04:59

题目链接:

http://codeforces.com/problemset/problem/325/B

题意:

给一个long long范围的n,问存在哪些数满足这个要求:设初始sum值为0,对于某个数k,无限除二直至它是一个奇数,在这个过程中sum值加上每次除二得数,并加上最后奇数x的一个值x * (x-1) / 2

思路:

容易知道最后的xn内且最大值略比n的开方大些。假设原始k值需要除n2才能得到x,于是又,其中n0的情况需要讨论下。

血的教训再次证明多项式在ACM中用二分穷举答案是最靠谱的。注意添加退出条件,注意计算x*2n次方时会爆long long,因此枚举x的上界需要随n的增大做调整减小。

源码:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <iostream>

#include <algorithm>

using namespace std;

typedef long long LL;

const LL MAXN = 1e18+1;

LL out[100];

int cnt;

LL up;

LL cal(LL t1,LL x)

{

    return x * (x - 1) / 2 + (t1 - 1) * x;

}

LL fi(LL n, LL t1)

{

    LL ri,le;

    le = 0;

    ri = up;

    while(ri - le > 1){

        LL mid = (ri + le) / 2;

//        printf("cal(le) = %I64d,cal(ri) = %I64d,cal(mid) = %I64d\n",cal(t1,le),cal(t1,ri),cal(t1,mid));

//        printf("le = %I64d,ri = %I64d\n",le,ri);

//        system("pause");

        if(cal(t1,mid) == n){

//            printf("t1 = %I64d\n",t1);

//            printf("mid = %I64d,cal(mid) = %I64d\n",mid,cal(t1,mid));

//            system("pause");

            return mid;

        }

        else if(cal(t1, mid) > n)

            ri = mid;

        else if(cal(t1,mid) < n)

            le = mid;

    }

//    printf("t = %I64d,le = %I64d,ri = %I64d\n",t1,le,ri);

//    printf("cal(le) = %I64d,cal(ri) = %I64d\n",cal(t1,le),cal(t1,ri));

//    system("pause");

    up = ri;

    if(cal(t1,ri) == n)

        return ri;

    else if(cal(t1,le) == n)

        return le;

    else if(ri==1 && le == 0)

        return 0;

    return -1;

}

int main()

{

    LL n;

    while(scanf("%I64d",&n) != EOF){

        cnt = 0;

        up = sqrt(4 * n);

//        if((sqrt(1 + 8 * n) * sqrt(1 + 8 * n) == 1 + 8 * n) && ((1 + sqrt(1+8*n)) % 2 == 0))

//            out[cnt++] = (1 + sqrt(1 + 8 * n)) / 2;

        LL t1 = 1;

        while(1){

            LL temp = fi(n, t1);

//            printf("temp = %I64d\n",temp);

//            system("pause");

            if(temp == 0)

                break;

            else if(temp != -1 && temp%2 != 0)

                out[cnt++] = temp * t1;

            t1 *= 2;

        }

        sort(out, out+cnt);

        if(cnt > 0){

            for(int i=0; i<cnt; i++){

                if(i>0 && out[i] == out[i-1])

                    continue;

                printf("%I64d\n",out[i]);

            }

        }

        else

            printf("-1\n");

    }

    return 0;

}

 

 

0 0