Timus 1117

纠结了一天也没有想到怎么用DP来做,看了看大牛的想法顿时茅塞顿开:

结果是要求从i到j需要多少天,假如用res[i][j]来表示,那么假如我们知道res[1][i]和res[1][j]的话,res[i][j]=res[1][j]-res[1][i] (i<=j),因此转化为求res[1][i]和res[1][j];

而2的整数次幂可以直接求出若用r[i]表示res[1][2^i]的结果r[i]=2*r[i-1]+i-1;画一画就可以看得出来。

然后根据r[i]的值递归求任何一个res[1][k],如何递归呢?

拿个Res[1][11]来说吧:

先找出大于11的最大2的整数次幂8;

Res[1][11]=res[1][8]+res[8][11];

根据对称性可以将res[8][11]变为res[5][8],因此

Res[1][11]=res[1][8]+res[5][8]=res[1][8]+(res[1][8]-res[1][5])=2*res[1][8]-res[1][5];

最终 res[1][11]=2*res[1][8]-res[1][5]; 还可以将res[1][5]不断分解。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
unsigned int res[35];
int findLayer(unsigned int k)
{
    int i;
    for(i=0;i<=31;i++)
        if((unsigned int)(1<<i)>k) return i-1;
    return 0;
}
int dfs(int k)
{
    int layer=findLayer(k);
    if(1<<layer==k) return res[layer];
    return 2*res[layer]-dfs((1<<(layer+1))-k);
}
int main()
{
    int i,s,t,temp;
    for(i=1;i<=31;i++) res[i]=2*res[i-1]+i-1;
    while(scanf("%d %d",&s,&t)!=EOF)
    {
        if(s>t) temp=s,s=t,t=temp;
        printf("%d\n",dfs(t)-dfs(s));
    }
    return 0;
}
posted @ 2012-05-21 17:44  书山有路,学海无涯  阅读(210)  评论(0编辑  收藏  举报