原题网址https://www.nowcoder.com/acm/contest/122/H
观察此题的数据10的18次方,一般情况下肯定会超时。结合之前做过的数列问题,无非就是找规律,多数情况下存在循环结。但是手动阀计算了几个数据后发现并不是那么简单。此题不是用循环结求解。于是用过程序打印出200个数据,规律仍没找到,但收获有一条:n出现第一次的位置为2的n次方减1。于是思路转向推导公式
f[n]=f[n/2]+f[n%2]
(1)当n为偶数时f[n%2]=f[0]=0,所以f[n]=[n/2]若是n/2仍未偶数时,继续往下推。
(2)当n为奇数时f[n%2]=f[1]=1,所以在在这里将f[n/2]加一,f[n/2]计算方法又回到最初判断奇偶性上来了。
不过此题有点小坑的是提交后时间一直是1001ms
,本人以为像这种超时这么小的情况下,应该不是算法的问题,而是故意卡了一个硬件运行速度和编译运行速度的差异。所以讲n/=n/2
改为n>>=1
即可
#include<iostream>
#include<string>
typedef long long ll;
using namespace std;
ll pow(int a, int b) {
ll ans = 1, base = a;
while (b != 0) {
if (b & 1 != 0)
ans *= base;
base *= base;
b >>= 1;
}
return ans;
}
int main()
{
ll t;
ll n, first;
int res;
cin >> t;
while (t--)
{
cin >> n;
res = 0;
while (n != 0)
{
if (n % 2 != 0)
{
res += 1;
n >>=1;
}
else
n >>=1;
}
first = pow(2,res) - 1;
cout << res<<" "<<first<<endl;
}
return 0;
}