P3734 [HAOI2017]方案数题解
直接考虑不经过
根据题意,一个点可到达的其他点是把原来点坐标二进制表示下某些
再考虑障碍点。
记第
最后只剩下求
否则
为了方便得到答案,可以将终点
#include <bits/stdc++.h>
typedef long long LL;
int read()
{
int s = 0, f = 1;
char ch = getchar();
while (!(ch >= '0' && ch <= '9'))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
s = (s << 3) + (s << 1) + (ch ^ 48);
ch = getchar();
}
return s * f;
}
LL readll()
{
LL s = 0, f = 1;
char ch = getchar();
while (!(ch >= '0' && ch <= '9'))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
s = (s << 3) + (s << 1) + (ch ^ 48);
ch = getchar();
}
return s * f;
}
struct Block
{
LL x, y, z;
int xx, yy, zz;
} ;
LL n, m, r;
int o;
Block a[10005];
const int MOD = 998244353;
LL dp[70][70][70] = {{{0}}}, f[10005];
LL c[70][70] = {{0}};
LL comb(int n, int m)
{
if (c[n][m])
return c[n][m];
if (n == m || m == 0)
return c[n][m] = 1;
return c[n][m] = (comb(n - 1, m - 1) + comb(n - 1, m)) % MOD;
}
int count(LL x)
{
int cnt = 0;
for (; x; x -= x & -x)
cnt++;
return cnt;
}
inline bool chk(int i, int j)
{
return ((a[i].x & a[j].x) == a[i].x)
&& ((a[i].y & a[j].y) == a[i].y)
&& ((a[i].z & a[j].z) == a[i].z);
}
int main()
{
n = readll(), m = readll(), r = readll(), o = read();
for (int i = 1; i <= o; i++)
a[i].x = readll(), a[i].y = readll(), a[i].z = readll();
dp[0][0][0] = 1;
for (int i = 0; i <= 64; i++)
for (int j = 0; j <= 64; j++)
for (int k = 0; k <= 64; k++)
{
for (int ii = 0; ii < i; ii++)
dp[i][j][k] = (dp[i][j][k] + dp[ii][j][k] * comb(i, i - ii) % MOD) % MOD;
for (int jj = 0; jj < j; jj++)
dp[i][j][k] = (dp[i][j][k] + dp[i][jj][k] * comb(j, j - jj) % MOD) % MOD;
for (int kk = 0; kk < k; kk++)
dp[i][j][k] = (dp[i][j][k] + dp[i][j][kk] * comb(k, k - kk) % MOD) % MOD;
}
std::sort(a + 1, a + o + 1, [](Block p, Block q){
return (p.x != q.x) ? (p.x < q.x) : (p.y != q.y ? p.y < q.y : p.z < q.z);
});
a[++o].x = n, a[o].y = m, a[o].z = r;
for (int i = 1; i <= o; i++)
a[i].xx = count(a[i].x), a[i].yy = count(a[i].y), a[i].zz = count(a[i].z);
for (int i = 1; i <= o; i++)
{
f[i] = dp[a[i].xx][a[i].yy][a[i].zz];
for (int j = 1; j < i; j++)
if (chk(j, i))
f[i] = ((f[i] - dp[a[i].xx - a[j].xx][a[i].yy - a[j].yy][a[i].zz - a[j].zz] * f[j] % MOD) % MOD + MOD) % MOD;
}
printf("%lld\n", f[o]);
return 0;
}
这题真的能评黑吗