标签:Digits rp 题解 可以 一个点 Grid 序列 mathcal 2N
给定一个 \(H\times W\) 的数字矩阵,一共走 \(2N\) 步,任选一个起点,奇数步可以移动到同行的一个点,偶数步移动到同列的一个点,将路径上的数记录下来得到一个长度为 \(2N\) 的序列(不包括起点),问有多少种可能的序列。
观察到行数和列数很小,考虑可以状态压缩。
经过思考后我们可以设计一个很妙的状态,\(f[i][S]\) 表示走了 \(i\) 步,结束时在集合 \(S\) 中的列/行,有多少种序列。
显然有初始状态 \(f[0][2^{H} - 1] = 1\),并且如果 \(S\) 不同,那么两个序列一定不同,可以分开转移。
那么对于 \(S\) 相同的序列,我们枚举后面接的数是什么,然后根据这个数推出可以到达的行。
直接做是 \(\mathcal{O}(NHW(2^H+2^W))\),预处理后可以做到 \(\mathcal{O}((N+HW)(2^H+2^W))\)。
#define N 11
int n, m, k, a[N][N], f[2][1 << N], u[1 << N][N], v[1 << N][N];
char s[N];
int main() {
read(n), read(m), read(k);
rp(i, n){
scanf("%s", s + 1);
rp(j, m)a[i][j] = s[j] - '0';
}
int p = (1 << n) - 1, q = (1 << m) - 1;
rep(s, 1, p)rp(i, n)if((s >> (i - 1)) & 1)rp(j, m)u[s][a[i][j]] |= 1 << (j - 1);
rep(s, 1, q)rp(j, m)if((s >> (j - 1)) & 1)rp(i, n)v[s][a[i][j]] |= 1 << (i - 1);
f[0][p] = 1;
rp(T, k){
memset(f[1], 0, sizeof(f[1]));
rp(s, p)
rep(i, 0, 9)ad(f[1][u[s][i]], f[0][s]);
memset(f[0], 0, sizeof(f[0]));
rp(s, q)
rep(i, 0, 9)ad(f[0][v[s][i]], f[1][s]);
}
int ans = 0;
rep(j, 1, p)ad(ans, f[0][j]);
printf("%d\n", ans);
return 0;
}
标签:Digits,rp,题解,可以,一个点,Grid,序列,mathcal,2N 来源: https://www.cnblogs.com/SharpnessV/p/15635455.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。