题解:AT_abc138_f [ABC138F] Coincidence
前言
看到题解区都是数位 dp ,然而这题其实只需要稍稍分类讨论一下就行了。
思路
(以下提到的位、位数等描述都是在二进制下)。
一些显而易见的结论
关于位数
易发现,\(x\) 和 \(y\) 必定是位数相同的,(否则异或的结果位数必定等于其较大值,模的结果必定小于等于其较小值)。
关于每一位
结论
再然后,观察到对于每一位必定只有三种情况:
- \(y\) 中为 \(1\),\(x\) 中为 \(0\)。
- \(y\) 和 \(x\) 中都为 \(1\)。
- \(y\) 中为 \(0\),\(x\) 中为 \(0\)。
为什么?
以上三种在当前位上合法是显而易见的,而全部都是这三种情况则全部也就合法了。
但 \(y\) 中为 \(0\),\(x\) 中为 \(1\) 为什么不行呢?
假设第 \(i\) 位是第一个 \(y\) 中为 \(0\),\(x\) 中为 \(1\) 的位,则此时异或的结果必然会比模的结果多 \(2^{i-1}\) 而这在后面的 \(i-1\) 位是不可能补回来的。
做法
设 \(r\) 的位数为 \(rd\),\(l\) 的位数为 \(ld\)。
枚举 \(x\) 和 \(y\) 的位数,设位数为 \(i\)。
\(ld < i < rd\) 时
因为此时不会有上下界的问题,所以除了最高位之外所有位都有上面提到的三种情况,也就是说此时的答案为:
\(i = ld\) 时
从高位往地位遍历,设当前遍历到第 \(j\) 位。
\(l\) 的第 \(j\) 位为 \(1\)
此时只有 \(x\),\(y\) 的第 \(j\) 位都为 \(1\) 的情况不会超出范围,即只有一种情况,直接跳过看后面。
\(l\) 的第 \(j\) 位为 \(0\)
此时三种情况都是不会超出范围的,我们分开讨论:
\(y\) 和,\(x\) 中都为 \(1\)
这意味着之后 \(j-1\) 位无论怎么搞都是不会超出范围的,于是我们直接加上 \(3^{j-1}\) 。
其实并不行,这里需要在乘上一个系数,而这个系数是由其他的两种情况带来的。
其他情况
可以发现这两种情况对于后面的取值是没有影响的,但是却有两种不同的取值,于是我们将后面的答案乘上一个二,也即将上面提到的系数(初始化为一)乘上一个二。
\(i = rd\) 时
和 \(i = ld\) 的情况类似,只是当前位为一和为零的做法对调而已。
特判
当 \(ld = rd\) 时,以上的做法正确性是有问题的,于是需要特判。
一样是从高位往低位遍历,设当前到 \(j\) 位。
\(j\) 位上 \(l\) 为 \(0\),\(r\) 为 \(1\)
显然,这时无论什么情况都不会超。
如果这位 \(x\),\(y\) 都为 \(0\),则之后无论如何都不会比 \(r\) 大,此时的答案即为之后 \(j-1\) 位上只考虑 \(l\) 的方案数,参见 \(i = ld\) 时的做法。
\(x\),\(y\) 都为 \(1\) 时同理。
\(y\) 上为 \(1\),\(x\) 上为 \(0\) 时对后面没有影响,直接往后面遍历就行了。
\(j\) 位上 \(l\) 为 \(1\),\(r\) 为 \(0\)
可以发现这里没有一种情况不超界,直接跳出就行了。
其他情况
其他情况都只有一种取值,且对后面没有影响,直接跳过即可。
最后的特判
判一下 \(x=l,y=r\) 的情况是否合法,如是则答案加一。
代码
代码如下,有问题评论区见。
#include<iostream>
#include<cstdio>
#define ll long long
#define mod 1000000007
using namespace std;
ll l,r;
int main(){
scanf("%lld%lld",&l,&r);
if(r==1){
printf("1");
return 0;
}
ll cr=0,tr=r,cl=0,tl=l;
while(tr)
cr++,tr>>=1;
while(tl)
cl++,tl>>=1;
ll da=0,dda=1,qx=1,ddaa;
ll ans=0;
if(cl==cr){
for(ll i=cr-1;i>=1;i--){
if((r>>(i-1)&1)==(l>>(i-1)&1)){
if(i==1)ans++;
continue;
}
else if((r>>(i-1)&1)&&(l>>(i-1)&1)==0){
da=0,qx=1;
for(ll j=i-1;j>=1;j--){
if((l>>(j-1)&1)==0){
dda=1;
for(ll k=1;k<j;k++){
dda*=3;
dda%=mod;
}
da+=qx*dda%mod;
da%=mod;
qx*=2,qx%=mod;
}
}
da+=qx;
da%=mod;
ans+=da;
ans%=mod;
da=0,qx=1;
for(ll j=i-1;j>=1;j--){
if((r>>(j-1)&1)){
dda=1;
for(ll k=1;k<j;k++){
dda*=3;
dda%=mod;
}
da+=qx*dda%mod;
da%=mod;
qx*=2,qx%=mod;
}
}
da+=qx;
da%=mod;
ans+=da;
ans%=mod;
if(i==1)ans++;
}
else break;
}
printf("%lld",ans);
return 0;
}
for(ll i=cr-1;i>=1;i--){
if(r>>(i-1)&1){
dda=1,ddaa=1;
for(ll j=1;j<i;j++){
dda*=3;
dda%=mod;
}
da+=qx*dda%mod;
da%=mod;
qx*=2;
qx%=mod;
}
}
da+=qx;
da%=mod;
ans+=da;
ans%=mod;
for(ll i=cl+1;i<cr;i++){
da=1;
for(ll j=1;j<i;j++){
da*=3;
da%=mod;
}
ans+=da;
ans%=mod;
}
da=0,qx=1;
for(ll i=cl-1;i>=1;i--){
if((l>>(i-1)&1)==0){
dda=1;
for(ll j=1;j<i;j++){
dda*=3;
dda%=mod;
}
da+=qx*dda%mod;
da%=mod;
qx*=2,qx%=mod;
}
}
da+=qx;
da%=mod;
ans+=da;
ans%=mod;
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号