有\(2N\)个玩家玩剪刀石头布游戏,分别从\(1\)到\(2N\)进行标号,这个游戏一共有\(M\)个回合,每个回合按照玩家排名两两对决。每个回合结束后,玩家的排名先按照分数大小排名,倘若分数相同,则标号小的玩家排在前列。求\(M\)回合后的玩家排名。
2 3
GCP
PPP
CCC
PPC
3
1
2
4
由于N和M都较小,可以根据题意直接模拟每回合的决斗情况,并在每回合结束后进行一次排序,时间复杂度为\(NMlogN\)。
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false);cout.tie(0);cin.tie(0); #define int long long #define fi first #define se second using namespace std; const int N = 60, M = 110; typedef pair<int,int> PII; char g[M][M]; struct Node { int id, val; bool operator < (const Node&T) const { if (val < T.val) return false; if (T.val < val) return true; return id < T.id; } }a[M+100]; int n, m; inline int check(char a, char b) { if (a == 'G') { if (b == 'G') return 0; if (b == 'C') return 1; if (b == 'P') return -1; } if (a == 'C') { if (b == 'C') return 0; if (b == 'P') return 1; if (b == 'G') return -1; } if (a == 'P') { if (b == 'P') return 0; if (b == 'G') return 1; if (b == 'C') return -1; } } signed main(void) { IOS cin >> n >> m; for (int i = 1; i <= 2*n; ++i) for (int j = 1; j <= m; ++j) { cin >> g[i][j]; a[i].id = i; } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { int s1 = a[2 * j - 1].id, s2 = a[2 * j].id; int res = check(g[s1][i],g[s2][i]); if (res == 1) a[2 * j -1].val ++; else if (res == -1) a[2 * j].val ++; } sort(a+1,a+2*n+1); } for (int i = 1; i <= 2 * n; ++i) cout << a[i].id << '\n'; return 0; }
给定两个非递减的序列A和B,构造一个满足\(a_i<=c_i<=b_i\)的非递减序列C。
2
1 1
2 3
5
\((1,1),(1,2),(1,3),(2,2),(2,3)\)共五个
定义\(f[i][j]\)为前\(i\)项中以\(j\)结尾的非递减序列的可能总数,那么可以得到转移方程
\(f[i][j] = f[i-1][0]+f[i-1][1]+....=\sum_{}f[i-1][k],a_{i-1} <=k<=j\)
于是我们可以发现累加的过程中可以使用一个前缀和数组来进行优化,我们定义\(sum[i][j]\)为前\(i\)项且第\(i\)项小于等于j的总可能数,转移方程就可以优化成:
\(f[i][j] = sum[i-1][j] - sum[i-1][a_{i-1}-1]\)
#include <bits/stdc++.h> #define int long long #define IOS ios::sync_with_stdio(false);cout.tie(0);cin.tie(0); using namespace std; const int mod = 998244353, N = 3100; int f[N][N], sum[N][N]; signed main(void) { IOS int n; cin >> n; vector<int> a(n+10), b(n+10); for (int i = 1; i <= n; ++i) cin >> a[i], ++a[i]; for (int i = 1; i <= n; ++i) cin >> b[i], ++b[i]; for (int i = a[1]; i <= b[1]; ++i) f[1][i] = 1, sum[1][i] = sum[1][i-1] + f[1][i]; for (int i = 2; i <= n; ++i) { for (int j = a[i]; j <= b[i]; ++j) { if (j >= a[i-1]) f[i][j] = (f[i][j] + sum[i-1][min(j, b[i-1])] - sum[i-1][max((long long)0, a[i-1]-1)] + mod) % mod; sum[i][j] = (sum[i][j-1] + f[i][j]) % mod; } } int ans = 0; for (int i = a[n]; i <= b[n]; ++i) { ans = (ans + f[n][i]) % mod; } cout << ans << '\n'; return 0; }