数列问题

原题网址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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值