いつもの桁DPと思い込み過ぎた。
http://agc015.contest.atcoder.jp/tasks/agc015_d
問題
閉区間[A,B]の範囲の整数を1つ以上選択し、それらのbitwise-orを取ることで得られる値は何通りか。
解法
f(A,B) := 閉区間[A,B]の範囲の整数を1つ以上選択し、それらのbitwise-orを取ることで得られる値
とする。
Bの最上位ビットをxとする。
Aもxの桁を持つ場合、どれを選んでもxのビットは立つのでf(A,B) = f(A^x,B^x)となり、探索する値を小さくすることができる。
以下そうでない場合を考える。
まず、複数の値のbitwise-orを取ると、最低でもそれらの最大値以上となることを前提とする。
- orを取る際xのビットを取らないようにする場合
- [A,x-1]の範囲のbitwise-orで得られる値なので、上記前提より[A,x-1]の(x-A)通り。
- orを取る際xのビットを取るようにする場合
- [x,B]の範囲の数値のみ使う場合を考える。xの次に立っているビット、すなわち(B-x)のMSBをyとすると、[x,x+2*y-1]の範囲の値がとれる。
- [A,x-1]と[x,B]両方の範囲の値を取る場合、[x+A,2*x-1]の範囲の値がとれる。
- 上記2つの範囲は重複することもあるので注意。
ll hoge(ll L,ll R) {
if(L==R) return 1;
ll r=1;
while(r*2<=R) r*=2;
if(L&r) return hoge(L^r,R^r);
ll k=1;
while(k<=(R^r)) k*=2;
//only a
ll ret=r-L;
// only B
ll x=r,y=r+k-1;
// A+B
ll a=r+L,b=2*r-1;
if(y<a) return ret+y-x+1+b-a+1;
else return ret+b-x+1;
}
void solve() {
int i,j,k,l,r,x,y; string s;
ll A,B;
cin>>A>>B;
cout<<hoge(A,B)<<endl;
}
まとめ
うーん、頭が固かった。