# NOI模拟（5.19） JSOID2T2 扫地机器人 （bzoj5318）

5.19 模拟 JSOI2018D2T2

1、我们只需要固定前d步，那么后面的每d步都应该和前d步是相同的;

2、这d步中有i步向下，d - i步向右，那么gcd(i, n) == 1,gcd(d - i, m) == 1;

Source:

/*
created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <ctime>
#include <deque>
#include <iterator>
#include <map>

static const int IN_LEN = 1024 * 1024;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}

// /*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (c = read(), iosig = false; !isdigit(c); c = read()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = read())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/

const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void write_char(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}

template<class T>
inline void W(T x) {
static int buf[30], cnt;
if (x == 0) write_char('0');
else {
if (x < 0) write_char('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) write_char(buf[cnt--]);
}
}

inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}

/*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (c = getchar(), iosig = false; !isdigit(c); c = getchar()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = getchar())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
// */

const int MAXN = 50 + 3;
const int mod = 998244353;

int t, n, m, d;
long long ans;
char s[MAXN];
int f[MAXN][MAXN], g[MAXN][MAXN];
bool a[MAXN << 1 | 1][MAXN << 1 | 1], ban[MAXN][MAXN];

inline void add(int &x, int t) {
((x += t) >= mod) && (x -= mod);
}

inline int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}

inline void solve(int p, int q) {
int sx = 1, sy = 1;
for (int i = 1; i <= p; ++i)
for (int j = 1; j <= q; ++j)
ban[i][j] = false;
// memset(ban, 0, sizeof(ban));
for (int c = 1; c <= n * m / d; ++c) {
for (int i = 1; i <= p; ++i)
for (int j = 1; j <= q; ++j)
f[i][j] = g[i][j] = 0;
f[p][q] = 1 - ban[p][q];
for (int i = p; i >= 1; --i)
for (int j = q; j >= 1; --j)
if (ban[i][j] == false)
for (int i = 1; i <= p; ++i)
for (int j = 1; j <= q; ++j)
ban[i][j] |= a[sx + i - 1][sy + j - 1];
sx += p - 1, ((sx > n) ? (sx -= n) : sx);
sy += q - 1, ((sy > m) ? (sy -= m) : sy);
g[1][1] = 1 - ban[1][1];
for (int i = 1; i <= p; ++i)
for (int j = 1; j <= q; ++j)
if (ban[i][j] == false)
for (int i = 1; i <= p; ++i)
for (int j = 1; j <= q; ++j)
if (ban[i][j] == false && (i != p || j != q))
ans = (ans + (long long)f[i][j] * g[i][j]) % mod;
}
}

inline void solve() {
R(n), R(m), d = gcd(n, m), ans = 0;
for (int i = 1; i <= n; ++i, read())
for (int j = 1; j <= m; ++j)
a[i][j] = a[i + n][j] = a[i][j + m]
= a[i + n][j + m] = read() - '0';
for (int i = 1; i <= d; ++i)
if (gcd(i, n) == 1 && gcd(d - i, m) == 1)
solve(i + 1, d - i + 1);
std::cout << ans << '\n';
}

int main() {
// freopen("in.in", "r", stdin);
R(t);
while (t--) solve();
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120