分治之替换

总时间限制: 
1000ms
内存限制: 
65536kB
描述

对于一个大于1的整数X,,你可以进行以下替换操作:

删掉它,把它换成三个数:⌊X/2⌋,X%2,⌊X/2⌋。

现在给你一个数列,开始数列只有一个整数N,你每次可以在数列中选择一个大于1的整数进行上述操作,直到这个数列最后全是1或0为止。

接下来,在最后的数列中查询区间[L,R]中有多少个1。输出1的个数。

0<N<=250,0<=R-L<=100000,并保证R不超过最终数列的长度。

输入
一行三个整数,分别表示N,L,R。
输出
一个整数,表示[L,R]区间有多少个1。
样例输入
10 3 10
样例输出
5
提示
【样例说明】
{10}→
{5 0 5}→
{2 1 2 0 5}→
{1 0 1 1 2 0 5}→
{1 0 1 1 1 0 1 0 5}→
{1 0 1 1 1 0 1 0 2 1 2}→
{1 0 1 1 1 0 1 0 1 0 1 1 2}→

{1 0 1 1 1 0 1 0 1 0 1 1 1 0 1}

解题思路: 

    这道题的数据范围为2^50,显然不能够使用整型数组来存放分解后所有的数字。观察一下规律,每一个数字都会被分解成三个数字,且最终都会被分解成0或1,所以可以考虑使用分治递归的方法来做,每个数字都会被一直分解成三个数字,一直分解到0或1.

    虽然说无法使用数组来存放所有的数字,但是我们是可以算出这个数列的长度的。观察一下上面分解10的时候的规律{10}->{5,0,5}->{2,0,2,0,2,0,2}->{1,0,1,1,1,0,1,0,1,0,1,1,1,0,1},第1次长度为1,第2次长度为3,第3次长度为7,第4次长度为15,找到规律长度为2^(分解次数+z-1,分解次数就是n除以2最终得到1或者0的除的次数。可以计算出数列的长度len

    那么(1,len)就是分治递归的范围。因为每一个数都会被分解成三个数,所以可以这样写

     return dg(n/2,l,mid-1)+dg(n%2,mid,mid)+dg(n/2,mid+1,r);

参考程序

#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;
LL n,L,R,len=1,x;
int tot;
int dg(LL n,LL l,LL r)
{
    if(R<l||L>r||n==0)//在区间(L,R)之外或者为0(出口1)
        return 0;
    if(n==1)//为1且在区间内就返回1(出口2)
        return 1;
    LL mid=(l+r)/2;//分治
    return dg(n/2,l,mid-1)+dg(n%2,mid,mid)+dg(n/2,mid+1,r);
}

int main()
{
    cin>>n>>L>>R;//输入区间(L,R)
    x=n;
    while(x>1)//计算出最后数组的长度len
    {
        x/=2;
        tot++;
    }
    len=pow(2,tot+1)-1;
    printf("%d",dg(n,1,len));//分治区间为(1,len)
    return 0;
}

### 算法分析中的替换法 在算法分析中,**替换法**通常被用来解决递推关系(Recurrence Relations),从而估算时间复杂度。这种方法的核心思想是通过假设和验证的方式逐步逼近解的形式,并最终得到精确的结果。 #### 替换法的基本流程 1. **猜测形式解**:基于经验或者观察模式,先对递推式的解做出一个合理的猜测。 2. **代入验证**:将这个猜测的解代回原递推式,检查其是否满足条件。 3. **调整并优化**:如果初始猜测不完全匹配,则适当修正该猜测直到它能够正确描述递推行为为止。 例如考虑如下经典的分治型递归方程: \[ T(n) = 2T\left(\frac{n}{2}\right)+n \] 我们可以尝试用替换法求解此问题的具体步骤如下所示[^4]: #### 示例解析 ##### 步骤一:设定初步猜想 对于上述递推关系, 我们可能会推测 \( T(n)=O(nlog⁡n)\), 这是因为每次划分都将规模减半的同时增加了线性的额外工作量. ##### 步骤二:展开递归树结构 继续深入探讨这个问题时发现实际上可以通过构建相应的递归树更直观地看到每一层的工作负载分布情况: - 层次0: n 节点数 * c 单位操作代价 => cn 总成本. - 层次1: (n/2)+(n/2)==n节点总数不变依旧保持cn总开销... 以此类推直至叶子结点数量等于输入数据大小停止扩展过程. 因此每级贡献相同均为cn, 整棵树高度大约lg⁡n所以总体累积起来就是\( O(n log ⁡n )\)级别性能表现. 以下是实现这一逻辑的一个Python伪代码片段展示如何利用循环模拟递归计算整个序列长度过程中涉及的各项参数变化趋势图象绘制功能模块部分省略未给出具体细节只保留核心框架便于理解主要思路即可: ```python def recursive_cost(n): if n == 1: return 1 else: cost = 2 * recursive_cost(n // 2) + n return cost # Example usage of the function to demonstrate growth pattern for i in range(1, 17): print(f"Cost at level {i}: ",recursive_cost(i)) ``` 以上程序段落清晰展现了随着层数增加整体花费呈现稳定增长态势进一步印证前面理论分析结论准确性毋庸置疑值得信赖推广应用于更多实际场景当中去解决问题创造价值最大化目标达成一致认可好评不断持续改进完善版本迭代更新维护长久有效运行下去造福社会大众群体共同进步成长共创美好未来世界明天会更好加油努力奋斗吧少年少女们!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值