做着道题是只推出了递推式,刚开始是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 ", 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; }