hihocoder 1577

在Hiho王国受到外敌入侵之际,国王决定利用随机选取的连续兵马段与全体兵马进行配对,形成战斗力为1的骑兵单位进行反击。本问题探讨如何计算这种随机策略下骑兵战斗力之和的期望值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#1577 : 为了Hiho的荣耀

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

Hiho王国受到外敌入侵,为了Hiho的荣耀,国王决定组织骑兵反击。一个骑兵单位由一个兵和一匹马组成,其战斗力为1。单个的兵、单个的马或两个兵、两个马都不是骑兵单位,故没有战斗。

国王发现他的兵马排成了有序的 A、B两行,每一行中都既可能有兵,又可能有马。国王宣布了本次反击的出战策略:在A中随机选择连续的一段(至少一个),称为SubA,将这一段的兵马从左到右依次编号为0, 1, 2, 3 ...;同时将B中全部的兵马从左到右依次编号为0, 1, 2, 3 ... 。然后将SubA与B中编号相同的配对,一对兵马SubAi和Bi参战的条件是:∀ 0 ≤ j ≤ i,SubAj与Bj都可组成骑兵单位。

注意,前文中SubA的选择是随机的,是指其中的每一段不论其长度、位置,被选择的概率都相同。国王想知道这次出击的骑兵的战斗力之和的期望,你能帮帮他吗?

输入

第一行有两个数字n 、m,分别代表A、B的兵马数量。

第二行n个数字A0, A1, ...An-1,表示A中的兵马,其中Ai=0代表兵,Ai=1代表马,数字之间没有任何分隔符。

第三行m个数字B0, B1, ... Bm-1 ,表示B的兵马,Bi的形式和意义同上。

对于30%的数据,  1 ≤ n, m ≤ 50

对于50%的数据,  1 ≤ n, m ≤ 1000

对于100%的数据,1 ≤ n, m ≤ 1000000

输出

输出只有一行,包含一个小数,表示此次出击战斗力之和的期望。只要你的答案和标准答案相差不超过0.01就被视为是正确的。

样例输入

6 6
010101
101011

样例输出

1.57142857
#include <iostream>
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int MX=1000000+1000;
int n,m;
char stra[MX],strb[MX];
int nex[MX];

void kmp_nex(char *s)
{
    nex[0]=-1;
    int k=-1,i=0;
    int len=strlen(s);
    while(s[i])
    {
        if(k==-1||s[i]==s[k])
        {
            k++;i++;
            nex[i]=k;
        }
        else
        {
            k=nex[k];
        }
    }

}
ll KMP(char *ostr,char *mstr)
{
    int i=0,j=0;
    ll res=0;
    kmp_nex(mstr);
    while(ostr[i] )
    {
        if(j==-1 || ostr[i]==mstr[j])
        {
            ++i;
            ++j;
            if(mstr[j]==0)
            {
                res+=(ll)(j+1)*j/2+(ll)(n-i)*j;
                j=nex[j];
            }
        }
          else
          {
              res+=(ll)(j+1)*j/2+(ll)(n-i)*j;
              j=nex[j];
          }

    }
    return res;
}


int main()
{
    while(cin>>n>>m)
    {
        scanf("%s%s",stra,strb);
        stra[n]='#';stra[n+1]=0;
        for(int i=0;i<m;i++)
        {
            if(strb[i]=='0') strb[i]='1';
            else strb[i]='0';
        }
        ll res=KMP(stra,strb);
        ll k=(ll)(n+1)*(ll)n/2;
        printf("%.9lf\n",1.0*res/k);
    }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值