cats 的电脑中毒


2024 杭电多校(8) L
https://vjudge.net/problem/HDU-7528

题型描述

推公式

题目大意

定义两个 $01$ 串相邻当且仅当两个字符串只有一个字符不同。现在规定 $01$ 串长度是 $n$ ,在所有的 $2^n$ 个 $01$ 串中给出三个被感染的 $01$ 串,这些 $01$ 串每轮会把相邻的所有字符串感染,问经过多少轮之后,所有的 $01$ 串都被感染。

数据范围

$2<=n<=2\cdot10^5$

题解

首先定义两个字符串的距离:
由于一个字符串与相邻的字符串只有一个字符不同
所以当两个字符串有 $n$ 个字符不同的时候,定义它们距离为 $n$

显然,每个长度为 $n$ 的字符串都有一个距离为 $n$ 的反串与之对应
对于感染的过程。

不难发现只有一个感染源的时候,以这个感染源开始感染,一直到这个感染源的尽头才能够全部感染,答案显然为 $n$。

我们任取三个感染源之一 $A$ 作为根,那么其余的感染源都在 $A$ 的感染路径上。

考虑如何做才能缩短感染的路径,同时保证感染进行完全:

  • 为了确保感染进行完全,其他的感染源必须回到感染起点或者感染终点,之后再掉头感染一遍。

  • 回到起点肯定会浪费更多之间,因为起点已经开始感染,所以肯定要去到感染终点,之后掉头向起点的方向感染。

这样就能形成一个相遇问题,减少走完全程需要的步骤。
而剩余的两个感染源中,我们选取离 $A$ 最远的感染源,记录距离为 $k$
则答案显然为 $floor(\frac{n+(n-k)}{2})$

推导到这里发现答案只与 $k$ 有关
而由于 $A$ 是任取的,所以实际上的 $k$ 应为三个感染源两两之间距离的最大值。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll mod=1e9+7;

void solve(){
    int n;
    cin>>n;
    string s1,s2,s3;
    cin>>s1>>s2>>s3;
    int cnt1=0,cnt2=0,cnt3=0;
    for(int i=0;i<n;++i){
        if(s1[i]!=s2[i])cnt1++;
        if(s3[i]!=s2[i])cnt2++;
        if(s1[i]!=s3[i])cnt3++;
    }
    int mx=max(cnt1,max(cnt2,cnt3));
    cout<<(2*n-mx)/2<<'\n';
}
int main() {
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int T=1;
    cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}

文章作者: paramec1um
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 paramec1um !
评论
  目录