2023大厂真题提交网址(含题解):
www.CodeFun2000.com(http://101.43.147.120/)
最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。
题目1:[HNOI2013]游走
题目大意
给你一张无向连通图,从第 1 1 1点随机游走到 n n n点。花费为经过的边的编号的和.问你如何安排边的编号使得期望花费最小化.
n ≤ 500 , m ≤ n 2 n \leq 500,m \leq n^2 n≤500,m≤n2
题目思路:
很容易想到,求出每条边期望经过次数,然后贪心安放即可.
但是 m m m太大,无法求解.考虑先求每个点期望经过次数.
考虑到 n n n点就停止了,所以不考虑 n n n的贡献。
显然有转移:
f 1 = 1 + ∑ ( 1 , j ) ∈ E f j d u j f_1=1+\sum_{(1,j)\in E}^{}\frac{f_j}{du_j} f1=1+∑(1,j)∈Edujfj
f n = 0 f_n=0 fn=0
f i = ∑ ( i , j ) ∈ E f j d u j , i ∈ [ 2 , n ) f_i=\sum_{(i,j)\in E}^{}\frac{f_j}{du_j}, \ i \in [2,n) fi=∑(i,j)∈Edujfj, i∈[2,n)
对于一条边 ( i , j ) (i,j) (i,j),它期望经过的次数是:
g i , j = f i d u i + f j d u j g_{i,j}=\frac{f_i}{du_i} + \frac{f_j}{du_j} gi,j=duifi+dujfj
所以跑高斯消元后,对边排序计算即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
const int maxn = 505;
const double eps = 1e-8;
vector<int> e[maxn];
int du[maxn];
double a[maxn][maxn];
double res[maxn] , ans[maxn * maxn];
int main()
{ios::sync_with_stdio(false);int n , m; cin >> n >> m;for (int i = 1 ; i <= m ; i++){int x , y; cin >> x >> y;e[x].pb(y);e[y].pb(x);du[x]++;du[y]++;}for (int i = 1 ; i <= n ; i++) a[i][i] = 1;for (int i = 1 ; i < n ; i++){for (auto v : e[i]){a[i][v] = -1.0 / du[v];}}a[1][n + 1] = 1;// guess消元int r , c;for (r = c = 1 ; r <= n && c <= n ; r++ , c++){int p = r;for (int j = r + 1 ; j <= n ; j++){if (a[p][c] < a[j][c]){p = j;break;}}// 不会有自由元swap(a[p] , a[r]);for (int j = 1 ; j <= n ; j++){if (j == r) continue;if (fabs(a[r][c]) < eps) continue;double d = a[j][c] / a[r][c];for (int k = c ; k <= n + 1 ; k++)a[j][k] -= d * a[r][k];}}for (int i = 1 ; i <= n ; i++) res[i] = a[i][n + 1] / a[i][i];int cnt = 0;for (int i = 1 ; i <= n ; i++){for (auto v : e[i]){if (v < i) continue;ans[++cnt] = res[i] / du[i] + res[v] / du[v];}}sort(ans + 1 , ans + 1 + cnt);double gg = 0;// cout << "cnt = " << cnt << endl;for (int i = 1 ; i <= cnt ; i++){gg += (cnt - i + 1.0) * ans[i];}cout << fixed << setprecision(3);cout << gg << endl;return 0;
}
题目2:bzoj3270-博物馆
题目大意:
给出一个无向图,两个人初始在两个点上。当一个人在一个点i上的时候,每一次,他有 p [ i ] p[i] p[i]的概率留在原位,有 1 − p [ i ] 1−p[i] 1−p[i]的概率等概率地选择直接连边的一个点走出去。当两个人在同一时刻走到同一个点,那么他们相遇,过程结束。现在求他们在每一个点相遇的概率。
题目思路:
跟题目1没本质区别,就是升维了。令 f ( i , j ) f(i,j) f(i,j)代表两个人从最开始到站在 i , j i,j i,j期望次数,然后大力转移即可.
题目3:2019HNCPC-H-有向图
题目大意:
给你一张图。 n + m n+m n+m个点。从1点开始随机游走。有一个概率矩阵 P i , j P_{i,j} Pi,j代表从 i 到 j i到j i到j的概率.后 m m m个点走到后则只会原地踏步.问你无限次之后停在后m个点的概率.
题目思路:
令 E ( i ) E(i) E(i)为无限次之后经过 i i i点的期望次数。由于到 i , i ∈ [ n + 1 , n + m ] i ,\ i \in[n+1,n +m] i, i∈[n+1,n+m]后就会停止。所以求解出来的期望就是概率。
转移和上述问题无差别,列方程高斯消元即可.
题目4:HDU5955-AC自动机+概率dp+高斯消元
题目大意:
n个人,每个人有一个长度为 L L L的字符串。你随机生成字符串无限次直到最后 L L L个字符串为某个人的字符串.问每个人的概率.
题目思路:
建Tire图。在Tire图上跑概率dp.然后高斯消元即可.
问题结构和题目3一模一样。我们可以直接求期望,然后概率=期望.