NC15979 小q的数列
题目
题目描述
小q最近迷上了各种好玩的数列,这天,他发现了一个有趣的数列,其递推公式如下:
\[f[i] =
\left\{
\begin{array}{l}
0 ,& i = 0\\
1 ,& i=1\\
f[i/2]+f[i\%2],& i\geq 2
\end{array}
\right.
\]
现在,他想考考你,问:给你一个 \(n\) \((n<10^{18})\),代表数列的第 \(n\) 项,你能不能马上说出 \(f[n]\) 的值是多少,以及 \(f[n]\) 所代表的值第一次出现在数列的哪一项中?
输入描述
输入第一行一个 \(t\)
随后 \(t\) 行,每行一个数 \(n\) ,代表你需要求数列的第 \(n\) 项,和相应的 \(n'\)
\((t<4 \cdot 10^5)\)
输出描述
输出每行两个正整数
\(f[n]\) 和 \(n'\) ,以空格分隔
示例1
输入
2
0
1
输出
0 0
1 1
题解
知识点:递归,数学。
按公式递归求值不难,接下来证明求最小 \(n'\)。
若把 \(n\) 看成二进制,公式可理解为 \(f[n>>1] + f[n\&1]\) ,即对于每位如果为 \(1\) 则加 \(1\) ,因此 \(f[n]\) 的结果是 \(n\) 二进制位为 \(1\) 的数量。那么一个数 \(n'\) , \(f[n']\)与 $f[n] $ 相同而且要最小,只要把 \(f[n]\) 个 \(1\) 从低位到高位排列,就能构造 \(n'\)。所以,\(n' = 2^{f[n]-1}\) 。
时间复杂度 \(O(\log n)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
using namespace std;
int f(long long n) {
if (n == 0 || n == 1) return n;
return f(n / 2) + f(n % 2);
}
int main() {
int t;
cin >> t;
while (t--) {
long long n;
cin >> n;
int ans = f(n);
cout << ans << ' ' << ((1LL << ans) - 1) << '\n';
}
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16403229.html