20201023 day43 模拟(十六)

1 The magic of WHH

problem

长为(n)的序列,每次可以将相同数字之间的其他数字变成这个数字,可以得到多少种不同的序列?可以不操作。

solution

([i,j])之间的颜色相同,则([i,j])之间的操作是没有必要进行的。即每个位置只能与两侧最近的同色位置操作。
(f(i))表示只考虑前(i)个位置的方案数,考虑加入位置(i)而上一个与(i)相同的位置是(j)

  1. 若这样的(j)不存在,则加入的位置没有贡献,(f(i)=f(i-1))
  2. 如果存在,就要加上把([j,i])染上颜色的贡献,此时注意(j=i-1)时染色是无效的,不会产生新的方案。

于是有(f(i)=f(i-1)+[i-j>1]f(j)),加上(f(j))是因为将([j,i])染色后,不影响(j)向前染色。

thoughts

0pts:统计数字出现的个数,用组合数的知识。(一个随随便便想想都知道极其错误的方法)
0pts:用队列维护区间长度。(其实这种模拟起来很复杂的题应该果断放弃模拟?)

code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int read()
{
	int a = 0,x = 1;char ch = getchar();
	while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
	while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
	return a*x;
}
const int N=1e6+7;
const ll P=1e9+7;
int t[N],arr[N];
ll f[N];
int main()
{
	int n = read();f[0] = 1;
	for(int i = 1;i <= n;i ++) {
		arr[i] = read();f[i] = f[i-1];
		if(t[arr[i]] && t[arr[i]] != i-1) (f[i] += f[t[arr[i]]])%=P;
		t[arr[i]] = i;
	}
	printf("%lld",f[n]);
	return 0;
}

2 The boxing of WHH

problem

每次比赛小A获胜和失败的概率都是(dfrac{1}{p+2}),平局的概率是(dfrac{p}{p+2})。如果小A的获胜场数大于落败场次,且平局次数为(k),则能获得(k+1)的分数。求获得分数的期望,在模998244353的意义下。

thoughts

可以假定胜负都有1种方案,平局有(p)种方案,最终乘以((p+2)^{-n})即可。
枚举有(i)次胜利或失败,有(n-i)场平局,此时胜利次数大于失败的方案数是((x+x^{-1})^i)
展开后次数>0的项系数之和,即((x^2+1)^i)展开后系数(>i)的项系数之和。
((x^2+1)^i)用二项式定理直接展开并计算答案,复杂度(O(n^2))

solution

考虑优化计算((x^2+1)^i)展开后次数(>i)的项系数之和,记为(t(i))
用二项式定理可以得到

[t(i)=sum_{j=0}^i[2j>i]left( ^i_j ight)x^{2j} ]

(i)为奇数的时候,每个(2j>i)的一定对应了一个(2(i-j)<i),所以(t(i))一定是所有系数之和的一半,即(t(i)=2^{i-1})
(i)为偶数时,只要减去(j=dfrac{i}{2})这一项的系数,剩下的一样一一对应,(t(i)=dfrac{2^i-{ichoose{i/2}}}{2})
复杂度(O(n))

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include <iostream>
#include <queue>
using namespace std;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x*=10,x+=ch^48,ch=getchar();}
	return x*f;
}
typedef long long ll;
const int P = 998244353, inv2 = (P + 1) >> 1;
int add(int a, int b) {return a + b >= P ? a + b - P : a + b;}
void inc(int &a, int b) {a = add(a, b);}
void dec(int &a, int b) {a = add(a, P - b);}
int mul(int a, int b) {return 1LL * a * b % P;}
int fpow(int a, int b){
	int res = 1;
	while (b)
	{
		if (b & 1) res = mul(res, a);
		a = mul(a, a);
		b >>= 1;
	}
	return res;
}
const int N = 3e6 + 10;
int n, p, fac[N], invfac[N];
int binom(int x, int y)
{
	return mul(fac[x], mul(invfac[y], invfac[x - y]));
}
int main()
{
	n = read(), p = read();
	fac[0] = 1;
	for (int i = 1; i <= n; ++i)
		fac[i] = mul(fac[i - 1], i);
	invfac[n] = fpow(fac[n], P - 2);
	for (int i = n - 1; i >= 0; --i)
		invfac[i] = mul(invfac[i + 1], i + 1);
	int pw = fpow(p, n), ip = fpow(p, P - 2), bin = 1, ans = 0;
	for (int i = 0; i <= n; ++i)
	{
		int tmp = mul(binom(n, i), pw);
		if (i & 1)
			tmp = mul(tmp, bin);
		else
			tmp = mul(tmp, add(bin, P - binom(i, i >> 1)));
		tmp = mul(tmp, inv2);
		tmp = mul(tmp, n - i + 1);
		inc(ans, tmp);
		pw = mul(pw, ip);
		bin = add(bin, bin);
	}
	ans = mul(ans, fpow(fpow(p + 2, n), P - 2));
	write(ans);
	return 0;
}

3 The tower of WHH

problem

给定(n imes m)矩阵,每个位置有一个与其他位置不相同的值,考察任意(i imes j)的矩阵((iin [1,n],jin [1,m])),如果(i imes j)的矩阵有最大值和最小值(operatorname{Max,Min}),且(operatorname{Max}-operatorname{Min}=i imes j-1),则可以获得(i imes j)的贡献。如果考察所有可能的矩阵,求最终贡献。

thoughts

10pts/30pts:枚举每个矩形,检查其中的数字是否连续。复杂度(O(n^3m^3))(O(n^2m^2))
40pts/60pts:当(n=1)是变为一维问题,

solution

code

4 The knife of WHH

problem

solution

thoughts

code

原文地址:https://www.cnblogs.com/liuziwen0224/p/20201023day43-002.html