【P15245 [WC2026] 二进制】题解
前言
84+0+0 严肃打铁。反思。
解法
规定
由于
::::info[证明]
- 性质 1:两个数的最后一次操作不可能相同
- 性质 2:一次
\times 2 操作后面不可能有两个连续的+1 。
反证法,不妨两个数都经历过
那么操作的形式肯定是
设
对于上面的第一种情况,无论
对于第二种情况,容易想到的一种可能的操作是让
不过这么做不一定是最优的,例如当
观察这个最优的方案,相当于让
于是考虑送有可能后第二种情况的答案就是
故
写出代码,复杂度为
::::info[
#include<bits/stdc++.h>
#define ll long long
#define pb emplace_back
#define pii pair<int,int>
#define mkp make_pair
#define fir first
#define sec second
#define mod (998244353ll)
#define inf (1000000000000000000ll)
#define ppc __builtin_popcountll
using namespace std;
int t;
void init(int x,int t){return;}
ll binary(ll x,ll y){
ll ans=inf,z=0;
while((x<<1)<y){
z++;
x<<=1;
}
//情况1
for(ll i=0;i<=63;i++)
ans=min(ans,z+i+((y-x+i)>>z)+ppc((y-x+i)&((1ll<<z)-1)));
//情况2
z++;
x<<=1;
ans=min(ans,z+x-y);
return ans;
}
// signed main(){
// ios::sync_with_stdio(0);
// cin.tie(0),cout.tie(0);
// int c,t;
// cin>>c>>t;
// init(c,t);
// while(t--){
// ll x,y;cin>>x>>y;
// cout<<binary(x,y)<<"\n";
// }
// return 0;
// }
::::
优化
复杂度瓶颈有两个地方:
- 求
z ; - 从
0 到64 枚举i 。
求
z=0;
while((x<<1)<y){
z++;
x<<=1;
}
这部分简单推导公式可以转换为 log2 函数比较慢,可以用 63 减去二进制下的前导 0 个数替代 log2,实现如下:
int log2_fast(uint64_t x) {
return 63-__builtin_clzll(x);
}
对于从
-
- 因为
i\le 63 所以需要y-x\times2^z 二进制下后六位; -
只需要预处理出这三个数值确定后令操作步数最优的
唯一的难点在于确定上面的 2,可以先 __builtin_ctzll 求出二进制末尾连续 __builtin_popcountll,__builtin_clzll 与 __builtin_ctzll 三个函数的时间复杂度均为
::::info[
#include<bits/stdc++.h>
#define ll long long
#define pb emplace_back
#define pii pair<int,int>
#define mkp make_pair
#define fir first
#define sec second
#define mod (998244353ll)
#define inf (1000000000000000000ll)
#define ppc __builtin_popcountll
using namespace std;
int t;
ll pre[75][75][64];//第一维:相当于z;第二维:y-x扔掉后六位以后,末尾连续1的个数;第三维:后六位
void init(int x,int t){
for(int zip=0;zip<=64;zip++){//z
for(int prefix=0;prefix<=58;prefix++){//二进制下排除后六位后末尾连续1的个数
for(int aft=0;aft<64;aft++){//二进制下后六位
ll ans=inf;
ll yx=(((1ll<<prefix)-1)<<6)+aft;
for(ll i=0;i<=64;i++){
if(zip+i+((yx+i)>>zip)+ppc((yx+i)&((1ll<<zip)-1))<ans){
ans=zip+i+((yx+i)>>zip)+ppc((yx+i)&((1ll<<zip)-1));
pre[zip][prefix][aft]=i;
}
}
}
}
}
return;
}
int log2_fast(uint64_t x) {
return 63-__builtin_clzll(x);
}
ll binary(ll x,ll y){
ll z=log2_fast((y-1)/x);
x<<=z;
int cnt=__builtin_ctzll(((y-x)>>6)+1);
ll i=pre[z][cnt][(y-x)&63];
return min(z+i+((y-x+i)>>z)+ppc((y-x+i)&((1ll<<z)-1)),z+1+(x<<1)-y);
}
//signed main(){
// freopen("txt.txt","r",stdin);
// ios::sync_with_stdio(0);
// cin.tie(0),cout.tie(0);
// int c,t;
// cin>>c>>t;
// while(t--){
// ll x,y;cin>>x>>y;
// cout<<binary(x,y)<<"\n";
// }
// return 0;
//}
::::