0302模擬賽

T1

在這裏插入圖片描述在這裏插入圖片描述
直接搜索出來字符串的最小表示法,然後排列計算一下。

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
typedef long long LL;
int n, m, k, mx, a[12], f[12]; LL seq[60];
void Count() {
	int cnt = 0;
	for(int l = 1; l <= n; ++l) {
		LL tmp = 0;
		for(int r = l; r <= n; ++r) {
			tmp = tmp * 10 + a[r];
			seq[++cnt] = tmp;
		}
	}
	sort(seq + 1, seq + cnt + 1);
	cnt = unique(seq + 1, seq + cnt + 1) - seq - 1;
	if(cnt == m) ++f[mx];
}
void ser(int now) {
	if(now > n) { Count(); return; }
	a[now] = ++mx; ser(now+1); --mx;
	bool flg[12]; memset(flg, 0, sizeof flg);
	for(int i = 1; i < now; ++i)
		if(!flg[a[i]]) flg[a[now]=a[i]] = 1, ser(now+1);
}
inline int A(int n, int m) {
	int re = 1;
	for(int i = 1; i <= m; ++i)
		re = 1ll * re * (n-i+1) % mod;
	return re;
}
int main () {
	freopen("string.in", "r", stdin);
	freopen("string.out", "w", stdout);
	scanf("%d%d%d", &n, &m, &k);
	ser(1); int ans = 0;
	for(int i = 1; i <= n && i <= k; ++i)
		ans = (ans + 1ll * f[i] * A(k, i)) % mod;
	printf("%d\n", ans);
}

T2

在這裏插入圖片描述在這裏插入圖片描述
前50分就是裸的斯坦納樹(雖然這麼說我也沒寫過),就是狀壓+spfa轉移。那麼考慮到k小,總顏色多。用隨機化。
如果我們對所有顏色關於k作一個映射。那麼恰好枚舉到正確答案的概率爲k!/(k^k)。我們枚舉300次!枚舉到正確答案的概率大致爲85%。時間複雜度爲T*(3^k*nm+2^k*SPFA(nm,nm))
學了一發斯坦納樹。

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, K, ans = 0x3f3f3f3f;
int a[20][20], V[20][20], dp[17][17][(1<<7)+5], d[20][20], b[230], c[230];
const int dx[4] = { 1, -1, 0, 0 };
const int dy[4] = { 0, 0, 1, -1 };
struct node { int x, y; };
queue<node>q; bool vis[20][20];
void Solve() {
	random_shuffle(b + 1, b + n*m + 1);
	for(int i = 1; i <= K; ++i) c[b[i]] = i;
	for(int i = K+1; i <= n*m; ++i) c[b[i]] = rand()%K + 1;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			d[i][j] = c[a[i][j]] - 1;
	int S = 1<<K;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j) {
			for(int k = 0; k < S; ++k)
				dp[i][j][k] = inf;
			if(d[i][j] >= 0) dp[i][j][1<<d[i][j]] = V[i][j];
		}
	for(int i = 1; i < S; ++i) {
		for(int l = (i-1)&i; (l<<1) > i; l = (l-1)&i)
			for(int j = 1; j <= n; ++j)
				for(int k = 1; k <= m; ++k)
					dp[j][k][i] = min(dp[j][k][i], dp[j][k][l]+dp[j][k][i^l]-V[j][k]);
		for(int j = 1; j <= n; ++j)
			for(int k = 1; k <= m; ++k) {
				vis[j][k] = 0;
				if(dp[j][k][i] < ans)
					q.push((node){ j, k }), vis[j][k] = 1;
			}
		while(!q.empty()) {
			int u = q.front().x, v = q.front().y, x, y;
			for(int j = 0; j < 4; ++j)
				if(d[x=u+dx[j]][y=v+dy[j]] >= 0 && dp[u][v][i]+V[x][y] < ans && dp[u][v][i]+V[x][y] < dp[x][y][i]) {
					dp[x][y][i] = dp[u][v][i] + V[x][y];
					if(!vis[x][y]) q.push((node){ x, y }), vis[x][y] = 1;
				}
			q.pop(); vis[u][v] = 0;
		}
		for(int u = 1, x, y; u <= n; ++u)
			for(int v = 1; v <= n; ++v)
				for(int j = 0; j < 4; ++j)
					if(d[x=u+dx[j]][y=v+dy[j]] >= 0 && dp[u][v][i] + V[x][y] < dp[x][y][i|(1<<d[x][y])])
						dp[x][y][i|(1<<d[x][y])] = dp[u][v][i] + V[x][y];
	}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			ans = min(ans, dp[i][j][S-1]);
}
int main () {
	freopen("graph.in", "r", stdin);
	freopen("graph.out", "w", stdout);
	srand(200332);
	scanf("%d%d%d", &n, &m, &K);
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j) {
			scanf("%d", &a[i][j]);
			if(~a[i][j]) ++a[i][j];
		}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j) scanf("%d", &V[i][j]);
	for(int i = 1; i <= n*m; ++i) b[i] = i;
	for(int i = 0; i <= n+1; ++i)
		for(int j = 0; j <= m+1; ++j)
			if(i <= 0 || i > n || j <= 0 || j > n) d[i][j] = -1;
	int T = 400; while(T--) Solve();
	if(ans == inf) puts("-1");
	else printf("%d\n", ans);
}

T3

在這裏插入圖片描述
在這裏插入圖片描述
十分巧妙,有點神。
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 105;
const int mod = 1e9 + 7;
int k, k1, k2;
int up(LL *a, LL *b, LL *c) {
	for(int i = 0; i < k; ++i) {
		if(a[i] + c[i] == 2*b[i]) return i;
		if(b[i]-a[i] < c[i]-b[i]) a[i+1] = b[i], b[i+1] = 2*b[i]-a[i], c[i+1] = c[i];
		else a[i+1] = a[i], b[i+1] = 2*b[i]-c[i], c[i+1] = b[i];
	}
	return k;
}
int f[MAXN][MAXN][MAXN];
int dfs(int a, int b, int c) {
	if(a + b > c) return 0;
	if(!c) return 1;
	if(!a && b > k2) return 0;
	if(~f[a][b][c]) return f[a][b][c];
	
	if(a) f[a][b][c] = (dfs(a-1, b, c-1) + 2ll*dfs(a+1, b, c-1)) % mod;
	else {
		if(b) f[a][b][c] = (1ll*dfs(a, b+1, c-1) + dfs(a+1, b, c-1) + dfs(a, b-1, c-1)) % mod;
		else f[a][b][c] = (dfs(a, b+1, c-1) + 2ll*dfs(a+1, b, c-1)) % mod;
	}
	return f[a][b][c];
}
LL a[MAXN], b[MAXN], c[MAXN];
LL x[MAXN], z[MAXN], y[MAXN];
int main () {
	freopen("rabbits.in", "r", stdin);
	freopen("rabbits.out", "w", stdout);
	memset(f, -1, sizeof f);
	scanf("%lld%lld%lld", &a[0], &b[0], &c[0]);
	scanf("%lld%lld%lld", &x[0], &y[0], &z[0]);
	scanf("%d", &k);
	k1 = up(a, b, c), k2 = up(x, y, z);
	int d1 = -1, d2 = -1;
	for(int i = 0; i <= k1; ++i) {
		bool flg = 0;
		for(int j = 0; j <= k2; ++j)
			if(a[i] == x[j] && b[i] == y[j] && c[i] == z[j])
			{ d1 = i, d2 = j; flg = 1; break; }
		if(flg) break;
	}
	if(~d1) printf("%d\n", dfs(d1, d2, k));
	else puts("0");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章