《2018 Multi-University Training Contest 9》
这场感觉难了不少。
Rikka with Nash Equilibrium:
一开始打了个表,发现最大值放在每个位置的贡献都一样。
然后就傻傻地找每个位置的组合数规律。。
结果是DP。这真没想到。
首先,很明显,那个纳什平衡数就是n * m。
那么我们从大到小填充矩阵,如果当前用了k个数组成了i,j个那么下一个数肯定要放在这i行或者j列中。
所以dp[k][i][j] 表示放置了k个数,覆盖了i行,j列。
从三个方向转移。
1:没有行列增加,如果之前放置了k - 1个数覆盖了i行j列,那么剩下还有i * j - (k - 1)个位置可以放置。
2:增加了一行,有n - (i -1) * j个位置可以放置。
3:增加了一列,有m - (j-1) * i个位置可以放置。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 1e5 + 5; const int M = 1e5 + 5; const LL Mod = 199999; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline int read(){ int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; LL dp[80 * 80 + 5][85][85];//放置k个点,且已经放置了i行,j列的方案数 int main() { int ca;ca = read(); while(ca--) { memset(dp,0,sizeof(dp)); int n,m,mod;n = read(),m = read(),mod = read(); dp[1][1][1] = n * m; for(int k = 2;k <= n * m;++k) { for(int i = 1;i <= n;++i) { for(int j = 1;j <= m;++j) { if(i * j - k + 1 < 0) continue; int ma1 = dp[k - 1][i][j] * (i * j - k + 1); int ma2 = dp[k - 1][i - 1][j] * (n - i + 1) * j; int ma3 = dp[k - 1][i][j - 1] * (m - j + 1) * i; dp[k][i][j] = (dp[k][i][j] + dp[k - 1][i][j] * (i * j - k + 1)) % mod; if(i > 0) dp[k][i][j] = (dp[k][i][j] + dp[k - 1][i - 1][j] * (n - i + 1) * j) % mod; if(j > 0) dp[k][i][j] = (dp[k][i][j] + dp[k - 1][i][j - 1] * (m - j + 1) * i) % mod; } } } printf("%lld\n",dp[n * m][n][m]); } // system("pause"); return 0; }
Rikka with Badminton:
这题题意描述真的很模糊啊。
一开始题意是参加的所有人都能打上球。。
这里的题意是选出的人里能拿出最少两个拍子,一个球来打。只需要组成一组就行了。
首先我们考虑容斥,算可以的方案数就行。
我们分类讨论:首先什么的a不用管了。没影响。
若c = 0:
d = 0:都不行。
d = 1:需要b != 0
d > 1:都行。
若c != 0:
b = 0:需要d > 1
b = 1:需要d != 0
b > 1:都行。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 1e5 + 5; const int M = 1e5 + 5; const LL Mod = 998244353; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline int read(){ int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; LL quick_mi(LL a,LL b) { LL re = 1; while(b) { if(b & 1) re = re * a % Mod; a = a * a % Mod; b >>= 1; } return re; } LL mul(LL a,LL b) { return a * b % Mod; } LL add(LL a,LL b) { return (a + b) % Mod; } int main() { int ca;ca = read(); while(ca--) { int a,b,c,d; a = read(),b = read(),c = read(),d = read(); LL n = a + b + c + d; LL sum = quick_mi(2,n); LL ma1 = (quick_mi(2,b) - 1 - b + Mod) % Mod;;//b > 1 LL ma2 = (quick_mi(2,c) - 1) * ma1 % Mod * quick_mi(2,a + d);//c != 0,b > 1 LL ma3 = ((quick_mi(2,c) - 1) * b % Mod * (quick_mi(2,d) - 1) % Mod * quick_mi(2,a) % Mod + Mod) % Mod;//c != 0,b = 1,d != 0 LL ma4 = (quick_mi(2,d) - 1 - d + Mod) % Mod;//d > 1 LL ma5 = ((quick_mi(2,c) - 1) * ma4 % Mod * quick_mi(2,a) % Mod + Mod) % Mod;//c != 0,b == 0,d > 1 LL ans = ((ma2 + ma3) % Mod + ma5) % Mod; LL tmp1 = ma4 * quick_mi(2,a + b) % Mod;//c = 0,d > 1 LL tmp2 = (d * (quick_mi(2,b) - 1) % Mod * quick_mi(2,a) % Mod + Mod) % Mod;//c = 0,d = 1,b != 0 ans = ((ans + tmp1) % Mod + tmp2) % Mod; ans = (sum - ans + Mod) % Mod; printf("%lld\n",ans); } // system("pause"); return 0; }
Rikka with Stone-Paper-Scissors:
对于胜利的期望情况,就会存在失败。
也就是说我们当前选择了用这种状态胜利,就会导致其他状态的失败。
那么对于选择一种状态的期望就是 用这种状态胜利的期望 - 用这种状态失败的期望。
例如win(a) = a * c' / (a + b + c) - a * b' / (a + b + c)
这里还需要注意一点,gcd的值可能是负数。
这样我们做除法会导致符号变换。所以要对gcd取绝对值。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 1e5 + 5; const int M = 1e5 + 5; const LL Mod = 998244353; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int main() { int ca;ca = read(); while(ca--) { LL aa,bb,cc;aa = read(),bb = read(),cc = read(); LL a,b,c;a = read(),b = read(),c = read(); LL sum = a + b + c; LL ma1 = a * (cc - bb); LL ma2 = b * (aa - cc); LL ma3 = c * (bb - aa); LL ma = ma1 + ma2 + ma3; LL g = __gcd(ma,sum); g = abs(g); sum /= g,ma /= g; if(ma % sum == 0) printf("%lld\n",ma / sum); else printf("%lld/%lld\n",ma,sum); } //system("pause"); return 0; }