3084. 【NOIP2012模拟11.3】超级变变变

Description

经过一系列的游戏之后,你终于迎来了今天的作业,第一个作业是预习一个超级美好的函数f(x),描述如下。

 

 

 

为了研究这个函数的性质,你决定定义一次变化为x=f(x)。

若x就经过若干次变化为k,则你就会觉得这是一个k变变数。

现在既然你已经这么觉得了,那就只好给定A,B,求有多少个A<=x<=B是k变变数了。

Input

输入包含三行。

第一行为一个整数k。

第二行为一个整数A。

第三行为一个整数B。

Output

   输出仅一行,表示答案。

Sample Input

Sample Input 1
13
12345
67890123


Sample Input2
1
234567
1234567

Sample Output

Sample Output1
8387584

Sample Output2
1000001

Data Constraint

Hint

 对于50%的数据,0<=k,A,B<=10^6

对于100%的数据,0<=k,A,B<=10^18  A<=B

Solution

通过找规律可以发现:

1.若一个数x是奇数,那么能通过变换得到这个数的数是 x+1,x*2,x*2+1,x*4,x*4+1,x*4+2,x*4+3,x*8,x*8+1,x*8+2,x*8+3,x*8+4,x*8+5,x*8+6,x*8+7......

2.若x是偶数,那么能通过变换得到这个数的数是x*2,x*2+1,x*2+2,x*2+3,x*4,x*4+1,x*4+2,x*4+3,x*4+4,x*4+5,x*4+6,x*4+7,x*8,x*8+1......

注意要特判0的情况直接等于b-a+1

Code

#include<cstdio> 
#include<algorithm>
#define ll long long 
using namespace std;
ll k,a,b,ans=0;
void work(ll x,ll m){
	while(x<=b){
		if(x+m-1>=a){
			ans+=x+m-a;
			if(x>a) ans-=(x-a);
			if(x+m-1>b) ans-=x+m-1-b;
		}
		x*=2;
		m*=2;
	}
}
int main(){
	scanf("%lld%lld%lld",&k,&a,&b);
	if(!k){ans=b-a+1;} 
	else if(k&1) work(k,1);
	else{
		if(k+1>=a&&k+1<=b) ans++;
		work(k*2,4);
	}
	printf("%lld\n",ans);
	/*f[1]=k;int i=0,j=1;
	while(i<j){
		i=(i+1)%10000000;
		int x=f[i];
		if(x>=a) ans++;
		if(x*2<=b) f[j=(j+1)%10000000]=x*2;
		if(x%2==0&&x+1<=b) f[j=(j+1)%10000000]=x+1;
	}*/
	for(int k=12;k<=13;k++){
		for(int i=1;i<=700;i++){
			bool bz=0;
			int x=i;
			while(x){
				x=(x&1)?x-1:x/2;
				if(x==k){
					bz=1;
					break;
				}
			}
			if(!bz) continue;
			printf("%d ",i);
		}
		printf("\n");printf("\n");printf("\n");
	}
	return 0;
}


作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.youkuaiyun.com/zsjzliziyang/article/details/86618669

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值