纠结了一天也没有想到怎么用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; }