比赛地址:https://ac.nowcoder.com/acm/contest/11170#question

A:
分以下 3 种情况:
1、如果存在长度为 1 的极长全 1 子串,那么将这个子串反转,变为 0 ,答案减少 1 ,例如 100110011
2、如果存在一个 0 ,在两个全 1 子串中间,则把这个 0 反转变成 1 ,答案减少 1 ,例如 11101100
3、以上情况都没有,用O(n)复杂度算出权重,即答案

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    cin>>s;
    int ans=0,f=0;
    for(int i=0;i<s.size();)
    {
        int j,chang=0;
        for(j=i;j<s.size();j++)
        {
            if(s[j]=='0')    break;
            chang++;
        }
        if(chang==1)
        {
            f=1;
        }
        if(chang!=0)    ans++;
        i=j+1;
    }
    for(int i=1;i<s.size()-1;i++)
    {
        if(s[i]=='0'&&s[i-1]=='1'&&s[i+1]=='1')    f=1;
    }
    if(f==1)    cout<<ans-1<<endl;
    else    cout<<ans<<endl; 
    return 0;
}

B:
为了方便,以下题解及程序的数组下标从1开始(题目从0开始),用j表示a[j],k表示b[k],ansa表示a数组所有元素之和,ansb表示b数组所有元素之和。
我们分以下4种情况来分类讨论:
i = 1:j 和 k 必须 ≥ 2,则
          

i = 2:j 和 k 必须有一个 = 1,另外一个  ≥ 3,或者两个都是 1 ,则
          
i = 3:j 和 k 一个 = 1,一个 = 2,则
          
i ≥ 4:不可能有 j 和 k 满足条件,则
          
以上公式均没有加入取模运算,详情见代码
#include<bits/stdc++.h>
using namespace std;
const long long modd=998244353;
const int maxn=1e5+10;
long long a[maxn],b[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    long long ansa=0,ansb=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        ansa+=a[i];
        ansa%=modd;
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&b[i]);
        ansb+=b[i];
        ansb%=modd;
    }
    long long ans1,ans2;

    ans1=ansa-a[1],ans2=ansb-b[1];
    if(ans1<0)    ans1+=modd;
    if(ans2<0)    ans2+=modd;
    cout<<(ans1*ans2)%modd<<" ";

    ans1=ansa-a[2],ans2=ansb-b[2];
    if(ans1<0)    ans1+=modd;
    if(ans2<0)    ans2+=modd;
    ans1-=a[1],ans2-=b[1];
    if(ans1<0)    ans1+=modd;
    if(ans2<0)    ans2+=modd;
    cout<<(((ans1*b[1])%modd+(ans2*a[1])%modd)%modd+(a[1]*b[1])%modd)%modd<<" ";

    cout<<((a[1]*b[2])%modd+(b[1]*a[2])%modd)%modd<<" ";

    for(int i=4;i<=n;i++)
    {
        printf("0 ");
    }
    printf("\n");
    return 0;
}