题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5587
解题思路:
首先可以预处理第i天有多少个数以及前i天的数之和。
接下来就可以先二分找到最大的天数t,使其得到的数小于m,接下来就是如何求出多余的一截了。
这个地方卡了好久。。。一直没想到怎么处理好,其实可以用dfs去搜出来的。因为这里的数列是循环的,所以可以把它递归到最早的数列中。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
LL m,day[100],sum[100];
void init()
{
day[1] = 1;
sum[1] = 1;
for(int i = 2; i <= 63; i++) day[i] = day[i-1] * 2 + 1;
for(int i = 2; i <= 63; i++) sum[i] = sum[i-1] * 2 + day[i-1] + 1;
}
LL dfs(LL x)
{
if(x <= 1) return x;
int pos = lower_bound(day+1,day+1+63,x) - day;
if(day[pos] == x) return sum[pos];
return sum[pos-1] + dfs(x - day[pos-1] - 1) + x - day[pos-1];
}
int main()
{
int t;
scanf("%d",&t);
init();
while(t--)
{
scanf("%lld",&m);
printf("%lld\n",dfs(m));
}
return 0;
}