• [ABC200E] Minflip Summation


    一、题目

    题目描述

    一个字符串 (T) 是由一个包含 (0,1,?) 的字符串 (S) 循环连接 (k) 次获得的。

    字符串 (T) 中的每个 (?) 都可以换成 (0)(1),设得到的串是 (T'),求:

    [sum F(T') ]

    其中 (F(T')) 定义为把字符串通过区间异或 (1) 的方式变成相同的最小操作数。

    (1leq |S|leq 10^5,1leq kleq 10^9)

    解法

    别被题目吓到了,其实是个水题。

    首先想一想怎么才能做一个没有问号的序列 (S),可以把 (S) 差分,即得到数组 (s_1oplus s_2....s_{n}oplus s_1),不难发现这样做一定会有偶数个 (1),而且每次通过区间操作可以消掉一对 (1),并且 (S) 复制 (k) 次的差分数组就是 (S) 的差分数组复制 (k) 次获得的,不难写出答案:

    [k imes frac{sum_{i=1}^n[s_i=s_{i\%n+1}]}{2} ]

    然后再把问号考虑进来,可以先求出期望再乘以总方案数,只考虑 ([s_i=s_{i\%n+1}]) 的期望是好算的:

    • 如果 (s_i=?or s_{i\% n+1}=?),不难发现期望是 (50\%)
    • 否则期望是 ([s_i=s_{i\%n+1}])

    但是注意 (n=k=1) 并且字符是 (?) 的时候会出问题(期望算错了),需要特判。

    #include <cstdio>
    #include <cstring>
    const int M = 100005;
    const int MOD = 1e9+7;
    const int i2 = (MOD+1)/2;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,k,ans,t=1;char s[M];
    int qkpow(int a,int b)
    {
    	int r=1;
    	while(b>0)
    	{
    		if(b&1) r=r*a%MOD;
    		a=a*a%MOD;
    		b>>=1;
    	}
    	return r;
    }
    signed main()
    {
    	scanf("%s",s+1);k=read();
    	n=strlen(s+1);
    	if(n*k==1) {puts("0");return 0;}
    	for(int i=1;i<=n;i++)
    	{
    		int j=i%n+1;
    		if(s[i]=='?') t=t*2%MOD;
    		if(s[i]=='?' || s[j]=='?') ans=(ans+i2)%MOD;
    		else if(s[i]!=s[j]) ans++;
    	}
    	ans=ans*k%MOD*i2%MOD*qkpow(t,k)%MOD;
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    MySQL优化二 缓存参数优化
    Ant Design Pro 学习三 新建组件
    Ant Design Pro 学习二 新建菜单-布局
    因素空间从概率论、模糊集走向人工智能---汪培庄
    纪念L.A. Zadeh教授
    Configure the Stanford segmenter for NLTK
    navicat 连接sqlserver提示要安装 sql server native client
    CentOS6.5+nginx+tomcat负载均衡集群
    CentOS6.5安装mysql5.1.73
    linux64位操作系统装32位jdk解决方法
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14761606.html
Copyright © 2020-2023  润新知