前言
太妙啦!
本文只讲做法,不讲如何想到这个做法,没见过这个套路真的很难想啊。
题目
讲解
part1 01
我们先考虑没有问号的情况。
我们将所有数变为与第一个数相同的方法一定不劣。那么我们可以想到这样一个统计答案的方法,如果相邻两个数(按环考虑)不同,那么对答案的贡献为 (frac{1}{2})。用 (C++) 表示即:
[frac{overset{|S|}{underset{i=1}{sum}}S_i==S_{i\%|S|+1} ? 0 : 1}{2}
]
反复 (K) 次只需要将答案乘 (K) 即可。
part2 ?
考虑扩展版本。
我们发现每个 (?) 成为 (0) 和 (1) 的概率相同,而且彼此独立,所以我们可以求出期望再求出答案。
此时的答案为:
[Kcdot frac{overset{|S|}{underset{i=1}{sum}}f(i,i\%|S|+1)}{2}cdot 2^{cnt_?K}
]
其中的函数 (f(x,y)) 表示 (S_x,S_y) 对答案产生的贡献。
- (S_x) 与 (S_y) 其中一个是问号,那么显然对答案的贡献为 (frac{1}{2})。
- 否则相同贡献 (0),不同贡献 (1)。
代码
int qpow(int x,int y)
{
int ret = 1;
while(y){if(y & 1) ret = 1ll * ret * x % MOD;x = 1ll * x * x % MOD;y >>= 1;}
return ret;
}
int Add(int x,int y)
{
x += y; if(x >= MOD) x -= MOD;
return x;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%s",a+1);
n = strlen(a+1); k = Read();
for(int i = 1;i <= n;++ i)
{
int j = i+1 > n ? 1 : i+1;
if(a[i] == '?')
{
cnt++;
ans = Add(ans,inv2);
}
else if(a[j] == '?') ans = Add(ans,inv2);
else if(a[i] != a[j]) ans = Add(ans,1);
}
ans = 1ll * ans * k % MOD * inv2 % MOD * qpow(2,1ll * cnt * k % (MOD-1)) % MOD;
Put(ans);
return 0;
}