【数学】JZOJ_3084 超级变变变

本文探讨了一种特殊的数学函数f(x),并提出了一种高效算法来计算在指定区间内,该函数达到特定值K的数(称为K变变数)的数量。通过将问题转化为对数范围内的枚举,结合位运算和数学不等式的巧妙应用,文章提供了一个通用的解决方案,并附带了C++实现代码。

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

题意

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

思路

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

代码

#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、付费专栏及课程。

余额充值