AtCoder Beginner Contest 200 F
作者:互联网
这题的思路很清晰,和这题类似。
我们先考虑不将它重复\(k\)次,即字符串\(S\)所有的方案的和的平均数。
首先,若没有?
\(最少的次数=\lceil\frac{相邻两个数不同的个数}{2}\rceil\),那我们将每两个不同的字符的贡献看成\(\frac 1 2\),由于若相邻的不同的个数为奇数时要向上取整,我们发现,此时\(S_{|S|}\)和\(S_{1}\)一定不是同一个数,比如下面的情况
11100011000
所以,我们把\(|S|\)和\(1\)看成也是相邻的即可(类似环)。
有?
呢?
-
?+0/1 或 0/1+?
,可以计算贡献为\(\frac 1 4\)。 -
?+?
0+0
,1+1
贡献为0;0+1
,1+0
贡献为1。
即,总的贡献仍为\(\frac 1 4\)。
这样,我们计算出所有\(S\)的答案的平均数\(num\),我们先将其乘\(k\)(重复\(k\)次),得到重复\(k\)次的平均数。而我们有\(2^{kq}\)种方案,\(q\)指\(S\)中的?
的数量。所以,答案为:
注意:
当\(|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