其他分享
首页 > 其他分享> > AtCoder Beginner Contest 200 F

AtCoder Beginner Contest 200 F

作者:互联网

这题的思路很清晰,和这题类似。

我们先考虑不将它重复\(k\)次,即字符串\(S\)所有的方案的和的平均数

首先,若没有?\(最少的次数=\lceil\frac{相邻两个数不同的个数}{2}\rceil\),那我们将每两个不同的字符的贡献看成\(\frac 1 2\),由于若相邻的不同的个数为奇数时要向上取整,我们发现,此时\(S_{|S|}\)和\(S_{1}\)一定不是同一个数,比如下面的情况

11100011000

所以,我们把\(|S|\)和\(1\)看成也是相邻的即可(类似环)。

?呢?

这样,我们计算出所有\(S\)的答案的平均数\(num\),我们先将其乘\(k\)(重复\(k\)次),得到重复\(k\)次的平均数。而我们有\(2^{kq}\)种方案,\(q\)指\(S\)中的?的数量。所以,答案为:

\[num\times k\times 2^{kq} \]

注意:

当\(|S|=1\)且\(k=1\)时,不存在相邻的字符,我们应特判,输出0

代码:

#include<bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define sz(v) (int)(v).size()
#define all(v) (v).begin(),(v).end()

typedef long long ll;
typedef pair<int,int> pi;

const ll mod=1000000007;
const ll inv2=500000004,inv4=250000002;
ll k,cnt,ans;
string s;

ll qpow(ll x,ll y) {
	if(y==0ll) return 1;
	ll ret=qpow(x,y>>1ll);
	ret*=ret,ret%=mod;
	if(y&1ll) ret*=x,ret%=mod;
	return ret;
}

ll calc(char x,char y) {
	if(x=='?'||y=='?') return inv4;
	if(x!=y) return inv2;
	return 0;
}

int main() {
	cin>>s>>k;
	if(sz(s)==1&&k==1) {
		puts("0");
		exit(0);
	}
	for(int i=0;i<sz(s);i++) {
		ans+=calc(s[i],s[(i+1)%sz(s)]);
		cnt+=(s[i]=='?');
		ans%=mod;
	}
	ans=ans*k%mod*qpow(2ll,cnt*k)%mod;
	cout<<ans<<endl;
	return 0;
}

标签:AtCoder,return,Beginner,200,ll,ret,frac,mod,define
来源: https://www.cnblogs.com/Nastia/p/16461759.html