在这个特别的日子里祝全天下教师:
教师节快乐!!!
T1 lcs
两个小问:
1、原来的配方。
2、子序列对数同样是dp与第一小问一起求出。在求F[i][j]的同时,可以求出G[i][j]表示只考虑A[1. . i], B[1. . j]满足长度恰好为F[i][j]的公共子序列的对数。
◦ 考虑F的计算过程,直接将合法的转移统计入G[i][j]
◦ 去重。只有当F[i-1][j] = F[i][j-1] = F[i-1][j-1] = F[i][j]时,会多算一次G[i-1][j−1]的贡献。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005,mo = int(1e9) + 7;
char s[maxn],t[maxn];
int f[maxn][maxn],g[maxn][maxn],n,m;
int main()
{
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1),m = strlen(t + 1);
for(int i = 0;i <= n;i ++) g[i][0] = 1;
for(int i = 0;i <= m;i ++) g[0][i] = 1;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++)
{
f[i][j] = max(f[i - 1][j],f[i][j - 1]);
if (s[i] == t[j] && f[i - 1][j - 1] + 1 >= f[i][j])
{
f[i][j] = f[i - 1][j - 1] + 1;
g[i][j] = g[i - 1][j - 1];
}
if (f[i - 1][j] == f[i][j]) g[i][j] = (g[i][j] + g[i - 1][j]) % mo;
if (f[i][j - 1] == f[i][j]) g[i][j] = (g[i][j - 1] + g[i][j]) % mo;
if (f[i - 1][j] == f[i][j - 1] && f[i - 1][j - 1] == f[i - 1][j] && f[i - 1][j] == f[i][j])
g[i][j] = (g[i][j] - g[i - 1][j - 1]) % mo;
}
printf("%d\n%d\n", f[n][m], (g[n][m] + mo) % mo);
return 0;
}
T2 collision
一拿到题就想到某汝佳的蓝书上的第一题蚂蚁题…
然而我就是太过于依赖看书而没有实现过导致碰到见过的题都下不了手。
对于一次碰撞,我们可以视为两辆车继续沿着先前的方向行走,只是交换了编号。[居然没想到…看来晚上睡眠一定要好啊不然根本想不清问题]
那么对于时刻T,这些车的坐标是可以直接知道的。假如是往左的,那就是a[i]− T,否则是a[i]+ T。
每次碰撞后交换编号,相当于维持编号的相对顺序不发生改变。(即若原来编号i在编号j前,碰撞后依然是编号i在编号j前) 每次查询T, i,二分编号i的位置x,查询有多少车的坐标在x前即可判定。这个可以再分左右方向的车用一个二分统计。
T3 game
考试对题目的理解不是很到位,所以难以下手。
E[Ans]=∑xP(Ans=x)
=∑P(Ans>=x)
不妨考虑现在要求P(Ans ≥ x),对于每个叶子,假如权值≥ x ,那么将他权值设为1,否则设为0。现在相当于叶子中有m − x + 1个1,x − 1个0,问F[1]= 1的概率。
◦ 设G[u][x][0. . 1]表示u的子树中有x个0,F[u]= 0/1的方案数。G的合并非常简单,相当于做一个
树形背包。
◦
P(Ans>=x)=G[1][x][1](mx−1)
,求和即可。
读题要做到快又准,对时间要把握得更加到位,重视做过的每一道dp题。