jzoj3084-超级变变变【数学】

正题


题目大意

定义函数
f ( x ) { x − 1 ( x % 2 = = 1 ) x / 2 ( x % 2 = = 0 ) f(x)\left\{\begin{matrix} &x-1(x\%2==1)\\ & x/2(x\%2==0) \end{matrix}\right. f(x){x1(x%2==1)x/2(x%2==0)
一次变化是将 x = f ( x ) x=f(x) x=f(x)
A ∼ B A\sim B AB之间有多少个数可以变化到 k k k


解题思路

其实就是 f ( x ) = ⌊ x / 2 ⌋ f(x)=\lfloor x/2 \rfloor f(x)=x/2
计算 1 ∼ B 1\sim B 1B减去 1 ∼ A − 1 1\sim A-1 1A1
然后考虑倒推,若 x ≤ R x\leq R xR
⌊ 2 n k + x 2 n ⌋ = k \lfloor \frac{2^nk+x}{2^n} \rfloor=k 2n2nk+x=k
⌊ k + x 2 n ⌋ = k \lfloor k+\frac{x}{2^n} \rfloor=k k+2nx=k
因为 k k k为整数,直接调出
k + ⌊ x 2 n ⌋ = k k+\lfloor \frac{x}{2^n} \rfloor=k k+2nx=k
⌊ x 2 n ⌋ = 0 \lfloor \frac{x}{2^n} \rfloor=0 2nx=0
那么当 x &lt; 2 n x&lt;2^n x<2n 2 n k + x ≤ R 2^nk+x\leq R 2nk+xR
枚举 n n n,那么 x x x的可取个数 2 n 2^n 2n
k k k为偶数时,有可能是由 k + 1 k+1 k+1变来的,需要特判。


c o d e code code

#include<cstdio>
#define ll long long
using namespace std;
ll k,a,b,ans;
ll get_ans(ll x)
{
	if(k<=1) return x;
	ll z=1,ans=0;
	while(z*k<=x){
		ans+=z;
		if(z*k+z-1>x) ans-=z*k+z-1-x;
		z*=2;
	}
	return ans;
}
int main()
{
	scanf("%lld%lld%lld",&k,&a,&b);
	ans+=get_ans(b)-get_ans(a-1);
	if(k&&!(k&1)) k++,ans+=get_ans(b)-get_ans(a-1);
	printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值