Code Festival 2017 qualA E-Modern Painting
2017-09-26 20:44
375 查看
Description
给定一个n∗m的网格。一些人站在网格的边界上。一个人可以占据他面前的一行(列),过程是一直往前染色(每个人的颜色都不一样),直到下一个格子染上了颜色或者到达了边界。
显然不同顺序会有不同的最终状态。
求最终状态的方案数。
n,m≤105
Solution
好难啊,一点都不会做QAQ。可以先假设是竖直方向的人先占据格子。(水平情况一样计算)
因为若有L,R已经先占据了格子,那么(L,R)的格子也一定是会被竖直方向的人占领。
那么必定是一个区间[L,R]中的人一起先占据了一些格子。
考虑计算这种情况下的答案,答案就是下面三种数值的乘积:
考虑[1,L−1]的网格,按不同顺序所得到的答案。
考虑[R+1,m]的网格,按不同顺序所得到的答案。
考虑[L,R]的网格中,位置i有上下两个人可以选择占据。其贡献为2k。
现在只要计算出第一个值(第二个值方法类似)。
设面向右的人有X个,向下的Y个,向上的Z个。
其答案的形式一定是这样的。
把它下半部分的翻转一下就得到了一个相当于从(0,0)到(Y+Z,X)的路径方案数的东西(好大啊)。
因为必须要经过翻转的那一条边,所以贡献就是(X+Y+ZX)−(X+Y+Z−1X)=(X+Y+Z−1X−1)
然后存一下后缀前缀之类的搞一搞就好啦。
复杂度O(n+m)
#include <bits/stdc++.h> using namespace std; const int N = 301010; const int MOD = 998244353; const int INV = (MOD + 1) >> 1; typedef long long ll; char S ; int fac[N << 2], inv[N << 2]; int v [2], h [2]; int pre , suf , p2 ; int n, m, lim, ans; inline void Mod(int &x) { while (x >= MOD) x -= MOD; } inline int Pow(int a, int b) { int c = 1; while (b) { if (b & 1) c = (ll)c * a % MOD; b >>= 1; a = (ll)a * a % MOD; } return c; } inline int Inv(int x) { return Pow(x, MOD - 2); } inline int C(int n, int m) { return (ll)fac * inv[m] % MOD * inv[n - m] % MOD; } inline int Calc(int X, int Y, int Z) { if (X == 0) return (Y + Z) ? 0: 1; return C(X + Y + Z - 1, X - 1); } inline void Solve(void) { static int x, y, z; memset(p2, 0, sizeof p2); memset(suf, 0, sizeof suf); x = y = z = 0; for (int i = 1; i <= n; i++) x += h[i][1]; p2[0] = 1; for (int i = 1; i <= m; i++) Mod(p2[i] = p2[i - 1] << (v[i][0] & v[i][1])); for (int i = m; i; i--) { if (!v[i][0] && !v[i][1]) { suf[i] = suf[i + 1]; continue; } Mod(suf[i] = suf[i + 1] + (ll)Calc(x, y, z) * p2[i] % MOD); y += v[i][0]; z += v[i][1]; } x = y = z = 0; for (int i = 1; i <= n; i++) x += h[i][0]; for (int i = 1; i <= m; i++) { if (!v[i][0] && !v[i][1]) continue; pre[i] = (ll)Calc(x, y, z) * Inv(p2[i - 1]) % MOD; Mod(ans += (ll)pre[i] * suf[i] % MOD); y += v[i][0]; z += v[i][1]; } } int main(void) { freopen("1.in", "r", stdin); scanf("%d%d\n", &n, &m); lim = max(n, m) << 2; inv[1] = 1; for (int i = 2; i <= lim; i++) inv[i] = (ll)(MOD - MOD / i) * inv[MOD % i] % MOD; fac[0] = inv[0] = 1; for (int i = 1; i <= lim; i++) { fac[i] = (ll)fac[i - 1] * i % MOD; inv[i] = (ll)inv[i - 1] * inv[i] % MOD; } scanf("%s\n", S); for (int i = 1; i <= n; i++) h[i][0] = S[i - 1] - '0'; scanf("%s\n", S); for (int i = 1; i <= n; i++) h[i][1] = S[i - 1] - '0'; scanf("%s\n", S); for (int i = 1; i <= m; i++) v[i][0] = S[i - 1] - '0'; scanf("%s\n", S); for (int i = 1; i <= m; i++) v[i][1] = S[i - 1] - '0'; Solve(); lim >>= 2; for (int i = 1; i <= lim; i++) { swap(h[i][0], v[i][0]); swap(h[i][1], v[i][1]); } swap(n, m); Solve(); cout << max(ans, 1) << endl; }
相关文章推荐
- Code Festival 2017 qualA D Four Coloring[构造]
- Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning
- 【二分图染色】AtCoder CODE FESTIVAL 2017(qual B)C[3 Steps]题解
- Atcoder CODE FESTIVAL 2017 Final 简要题解
- [DP]Atcoder CODE FESTIVAL 2017 Final (Parallel) D - Zabuton
- CODE FESTIVAL 2017 qual B:C - 3 Steps 并查集判二分图、二分图性质
- B - Palindrome-phobia(CODE FESTIVAL 2017 Final)
- CODE FESTIVAL 2017 qual A C
- Atcoder CODE FESTIVAL 2017 qual C 总结+ABCD题解
- atcoder CODE FESTIVAL 2017 qual A 手速(雾)赛
- atcoder/CODE FESTIVAL 2017 qual B/B(dfs染色判断是否为二分图)
- [Atcoder CODE FESTIVAL 2017 qual C]D - Yet Another Palindrome Partitioning 状压DP
- 【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数
- 【AtCoder CODE FESTIVAL 2017 qual C】D - Yet Another Palindrome Partitioning (状压dp 字符串)
- CODE FESTIVAL 2017 qual C- A-B-C 总结
- 找规律 B - Palindrome-phobia(CODE FESTIVAL 2017 Final)
- Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) A. Andryusha and Socks
- 2016-2017 CT S03E05: Codeforces Trainings Season 3 Episode 5 (2016 Stanford Local Programming Contest, Extended) J
- Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017)C. Five Dimensional Points
- ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined) A