【数学】JZOJ_3084 超级变变变

题意

定义函数 f ( x ) f(x) f(x)为:
x x x为偶数, f ( x ) = x / 2 f(x)=x/2 f(x)=x/2
x x x为奇数, f ( x ) = x − 1 f(x)=x-1 f(x)=x1
如果数 x x x在变化过程中 ( x = f ( x ) ) (x=f(x)) (x=f(x))出现 x = k x=k x=k,那么我们把 x x x叫做 k k k变变数,求出区间 l ∼ r l\sim r lr k k k变变数的个数。

思路

其实 f ( x ) = ⌊ x / 2 ⌋ f(x)=\left \lfloor x/2 \right \rfloor f(x)=x/2,那么如果 2 n k + x 2^nk+x 2nk+x为变变数,满足
⌊ 2 n k + x 2 n ⌋ = k \left \lfloor \frac{2^nk+x}{2^n} \right \rfloor=k 2n2nk+x=k
显然是 x &lt; 2 n x&lt;2^n x<2n的,我们就可以枚举 x x x,那么每次可以贡献的答案数量就为 2 n 2^n 2n
如果 k k k为偶数,我们还有 x + 1 x+1 x+1转换过来的情况,所以答案要 ∗ 2 *2 2

代码

#include<cstdio>

long long k, a, b;

long long ask(long long n) {
	if (k <= 1) return n;
	long long g = 1, ans = 0;
	while (g * k <= n) {
		ans += g;
		if (g * k + g - 1 > n) ans -= g * k + g - 1 - n;//范围内
		g *= 2;
	}
	if (!(k & 1)) ans *= 2;
	return ans;
}

int main() {
	scanf("%lld %lld %lld", &k, &a, &b);
	printf("%lld", ask(b) - ask(a - 1));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值