HDU5587 递推式+二分 xingxing在努力

  做着道题是只推出了递推式,刚开始是1 接下来是1 1 2 =》 1 1 2 1 2 2 3我们可以推出式子d[(2^i)-1] = 2*d[2^(i-1)-1] + 2^(i-1)这个递推式, d[2^i-1]表示 数列前2^i-1项的和,求出这些以后我们可以给每一个d[2^i-1]+1就得到了前2^i次方项的和, 有了这些特殊点我们就可以通过二分找到一个查询M的最终答案。。代码如下:

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;
typedef long long LL;
LL d[65], mi[65];

LL getnum(LL M)
{
    //printf("M = %d\n", M);
    int idx = lower_bound(mi, mi+61, M)-mi;
    if(M == mi[idx])                    //假设要求解的点正好是特殊点则返回
        return d[idx];
    else 
    {
        idx--;
        LL tp = getnum(M-mi[idx]);
        return d[idx]+tp+M-mi[idx];      //还要加上新加的1
    }
}

int main()
{
    mi[0] = 1;
    for(int i=1; i<61; i++)
        mi[i] = 2*mi[i-1];
    d[1] = 1;
    for(int i=2; i<61; i++)
        d[i] = 2*d[i-1] + mi[i-1];
    for(int i=0; i<61; i++) d[i]++;
    int T;
    scanf("%d", &T);
    while(T--)
    {
        LL M;
        //scanf("%d", &M);
        cin>>M;
        cout<<getnum(M)<<endl;
    }
    return 0;
}

 

posted @ 2015-11-28 23:10  xing-xing  阅读(190)  评论(0编辑  收藏  举报