正题
题目大意
定义函数
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){x−1(x%2==1)x/2(x%2==0)
一次变化是将
x
=
f
(
x
)
x=f(x)
x=f(x)
求
A
∼
B
A\sim B
A∼B之间有多少个数可以变化到
k
k
k
解题思路
其实就是
f
(
x
)
=
⌊
x
/
2
⌋
f(x)=\lfloor x/2 \rfloor
f(x)=⌊x/2⌋
计算
1
∼
B
1\sim B
1∼B减去
1
∼
A
−
1
1\sim A-1
1∼A−1的
然后考虑倒推,若
x
≤
R
x\leq R
x≤R
⌊
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
<
2
n
x<2^n
x<2n且
2
n
k
+
x
≤
R
2^nk+x\leq R
2nk+x≤R
枚举
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);
}