题干:

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 < 250, 0 ≤ r - l ≤ 105, r ≥ 1, l ≥ 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.

题目大意:

   给一个数n,和一个区间[l,r] (r-l<1e5,n<2^50),每次需要把序列中大于1的数字分成(n/2,n%2,n/2)(其中n/2是向下取整),直到所有数变成0或1,问[l,r]区间内有多少个1?

解题报告:

    想着先把数字分好,然后再o(n)区间查询一下?有点麻烦,,其实分数字的过程中,答案就可以带出来了。

AC代码:

    

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
ll l,r;
ll dfs(ll n,ll curl,ll curr) {
	if(curl > r || curr < l) return 0 ;
	if(n == 1) return 1;
	ll res = 0;
	ll mid = (curl+curr)/2;
	if(n % 2 == 1 && (mid<=r && mid>=l)) res++;
	return res + dfs(n>>1,curl,mid-1) + dfs(n>>1,mid+1,curr);
}

int main()
{
	ll n,x,len = 1;
	cin>>n>>l>>r;
	x = n;
	while(x > 1) {
		len = len*2+1;
		x>>=1;
	}
	printf("%lld\n",dfs(n,1,len));
	return 0 ;
 }

总结:

  刚开始写代码的时候两个地方写萎了

    第一处:两个出口写颠倒了,想想也是不对啊,肯定是首先要在区间内部啊!!这是毋庸置疑的啊!!

    第二处:if(n % 2 == 1) res++;

 

至于为什么没有像线段树一样写上如果两者都在所求区间内部的话 单独返回一个值,这是因为我们提前把len算好了,所以最后分出的答案一定是0或者1,可以直接通过那个n==1来防止无限递归。然后就是对于0的处理,只需要那个res那里处理一下就可以了,因为只有中间的值才会出现等于0的情况,两边的值是不会出现为0的情况的,因为是除2操作嘛!!枚举几个终点可能值,就可以简单证明了,3/2=1,,,2/2=1,,,,1的话就是出口了,所以拆数的时候不会在两边有0出现,只可能是中间会有0出现。

所以其实这题我们也可以直接模拟一下过程,找找会有几个mid值是偶数,那么才会有0出现,假设求出0的数量是cnt0,那么结果就是r-l-cnt0。但是其实还是要模拟线段树build的过程的、、、、因为还要找和l,r的大小关系。

另附一个网络的二分思路的代码:(还未看)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, l, r, s = 1, ans;
void solve(ll a, ll b, ll l, ll r, ll d) { //二分的思想
	if ( a > b || l > r ) return;
	ll mid = (a+b)/2;
	if ( r < mid )solve(a,mid-1,l,r,d/2);
	else if( mid < l )solve(mid+1,b,l,r,d/2);
	else {
		ans += d%2;
		solve(a,mid-1,l,mid-1,d/2);
		solve(mid+1,b,mid+1,r,d/2);
	}
}
int main() {
	cin >> n >> l >> r;
	long long p = n;
	while ( p >= 2 ) {
		p /= 2;
		s = s*2+1;
	}
	solve(1,s,l,r,n);
	cout << ans << endl;
	return 0;
}