CodeForces - 768B Code For 1(找规律)

本文介绍了一个关于序列操作的问题,初始元素通过特定规则转换成由0和1组成的序列,目标是计算指定范围内1的数量。文章提供了算法思路及实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/problemset/problem/768/B点击打开链接


B. Code For 1
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Jon fought bravely to rescue the wildlings who were attacked by the white-walkers at Hardhome. On his arrival, Sam tells him that he wants to go to Oldtown to train at the Citadel to become a maester, so he can return and take the deceased Aemon's place as maester of Castle Black. Jon agrees to Sam's proposal and Sam sets off his journey to the Citadel. However becoming a trainee at the Citadel is not a cakewalk and hence the maesters at the Citadel gave Sam a problem to test his eligibility. 

Initially Sam has a list with a single element n. Then he has to perform certain operations on this list. In each operation Sam must remove any element x, such that x > 1, from the list and insert at the same position  sequentially. He must continue with these operations until all the elements in the list are either 0 or 1.

Now the masters want the total number of 1s in the range l to r (1-indexed). Sam wants to become a maester but unfortunately he cannot solve this problem. Can you help Sam to pass the eligibility test?

Input

The first line contains three integers nlr (0 ≤ n < 2500 ≤ r - l ≤ 105r ≥ 1l ≥ 1) – initial element and the range l to r.

It is guaranteed that r is not greater than the length of the final list.

Output

Output the total number of 1s in the range l to r in the final sequence.

Examples
input
7 2 5
output
4
input
10 3 10
output
5
Note

Consider first example:

Elements on positions from 2-nd to 5-th in list is [1, 1, 1, 1]. The number of ones is 4.

For the second example:

Elements on positions from 3-rd to 10-th in list is [1, 1, 1, 0, 1, 0, 1, 0]. The number of ones is 5.


仔细观察可以发现 每个数被拆分成的最终序列是有规律的 这里以10举例

先将该数用二进制表示 1010

观察序列 发现二进制中的第一位的1位于1 3 5 7 9 11 13 15的位置

第二位的0位于2 6 10 14

第三位的1位于4 12

第四位的0位于8

将1010这个二进制数的每一位附上权值 每一位对应为1 2 4 8 从左到右位置为 0 1 2 3 (其实就是2的次方对应关系)

于是可以发现 对于序列中任意一个位置的值 都具有以下规律

设当前位置为position 

position的值对应于 position的因子中最大的2的N次方数 即为该数二进制的第N位的值

有点难懂 还是举10的例子

对于序列的第3位 他的因子中最大的2的N次方数为1 即N=0 所以为二进制1010的第0位 也就是第一个1

对于序列的第6位 她的因子中最大的2的N次方数为2 即N=1 所以对应1010的第一个0

。。。。。。12。。。。。。。。。。。。。。。4 即N=2 所以对应第三位 也就是第二个1

找出规律之后 代码就很简单了

因为范围不大 因此枚举他需要的区间的每个位置 根据规律计算当前的数是不是1

#include <iostream>
#include <stdio.h>
#include <limits.h>
#include <stack>
#include <algorithm>
#include <queue>
#include <string.h>
#include <set>
using namespace std;
vector<long long int > s;
int main()
{
   long long int n,l,r;
   cin >> n >> l >> r;
   while(n!=0)
   {
       s.push_back(n%2);
       n/=2;
   }
   long long int cnt=0;
   reverse(s.begin(),s.end());
   s.push_back(0);
   for(long long int i=l;i<=r;i++)
   {
        long long int j=0;
        long long int mid=i;
        while(mid%2==0)
            j++,mid/=2;
        if(s[j]==1)
            cnt++;
   }
   cout << cnt;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值