SCAU---计算智能--1142 巡逻的士兵--找规律--logn复杂度(非递归【可以改进至O(1)复杂度】)

SCAU—计算智能–1142 巡逻的士兵–找规律–logn复杂度【可以改进至O(1)复杂度】

有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现要求统计按这样的方法,
总共可能有多少种不同的正好三个士兵去侦察的士兵组合方案。

注: 按上法得到少于三士兵的情况不统计。

1 <= N <= 2的32次方-1

输入格式
有多行(可能有上百行,尽量优化代码),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,输出针对N的方案数

直到没有数字

输入样例
10
4
0

输出样例
2
0

解题思路

常规方法是用递归、分治,但是仔细观察可以发现它是有规律的。

首先列举:

士兵数方案数规律
1020
2021
31(21 +20)
4022
51+
62(22 +21)
71-
8023
91+
102+
113+
124(23+22)
133-
142-
151-
16024
171+

可以发现规律:任取数n,当n是2正整数幂x时,方案数 t == 0,
然后由0递增,到(2x +2x-1)时,t 取最大,再递减,到2x+1时,减回0.

由此,要找到一个数的方案数,只要找到比它小的的 2最大幂即可得出。

例:
若士兵数 n = 14,比它小的 2最大幂为 23,
判断14 > 23+22,
所以方案数为14 - (23+22) = 2

代码如下

#include<stdio.h>
void th(unsigned long int n)
{
    unsigned long int k = n,b=1;
    while(k = k>>1)b = b<<1;//找到比n小的 2^最大幂
    printf("%d\n",(b + (b>>1)) >= n ? n - b:((b<<1) - n));
    /*若n比(2^b +2^(b-1))大时,输出方案数为 2^b+1,否则输出方案数为 n-2^b */
}

int main()
{
    unsigned long int n;
    scanf("%d",&n);
    while(n)
    {
        th(n);
        scanf("%d",&n);
    }
    return 0;
}

小改进

math.h 内求log的复杂度是o(1)
我代码里,

while(k = k>>1)b = b<<1;//找到比n小的 2^最大幂

这步操作实际上是在求 log2n 并向下取整,可以直接用函数 log(n)达到同样的效果。
因此理论上,这步操作可以是 o(1)级别的。
但这份代码已经是我两年前写的啦,也没办法提交OJ测试了,有兄弟试过的可以在评论区回复哈~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值