正题
题目大意
定义函数
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∼BA\sim BA∼B之间有多少个数可以变化到kkk
解题思路
其实就是f(x)=⌊x/2⌋f(x)=\lfloor x/2 \rfloorf(x)=⌊x/2⌋
计算1∼B1\sim B1∼B减去1∼A−11\sim A-11∼A−1的
然后考虑倒推,若x≤Rx\leq Rx≤R
⌊2nk+x2n⌋=k\lfloor \frac{2^nk+x}{2^n} \rfloor=k⌊2n2nk+x⌋=k
⌊k+x2n⌋=k\lfloor k+\frac{x}{2^n} \rfloor=k⌊k+2nx⌋=k
因为kkk为整数,直接调出
k+⌊x2n⌋=kk+\lfloor \frac{x}{2^n} \rfloor=kk+⌊2nx⌋=k
⌊x2n⌋=0\lfloor \frac{x}{2^n} \rfloor=0⌊2nx⌋=0
那么当x<2nx<2^nx<2n且2nk+x≤R2^nk+x\leq R2nk+x≤R
枚举nnn,那么xxx的可取个数2n2^n2n
当kkk为偶数时,有可能是由k+1k+1k+1变来的,需要特判。
codecodecode
#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);
}