20161108测试总结

T1

一眼看成博弈论…
这是一道数学题,很容易推出可以下棋的格子时固定的,$\gcd(a, b)$ 的倍数格子是可以被下到的,其他的都是下不到的。然后就没了。证明有 $\gcd(a, b) = \gcd(a, a - b) = \gcd(a, a + b)$ 然后题解表示脑补一下就好了…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <bits/stdc++.h>
using namespace std;
int T;
long long n, a, b;
inline void solve() {
cin >> n >> a >> b;
if (a > b) swap(a, b);
if (a + b > n && b - a == a) {
cout << "wfl\n";
return;
}
n /= __gcd(a, b);
if (n & 1)
cout << "lidian\n";
else
cout << "wfl\n";
}
int main() {
cin >> T;
for (int i = 0; i < T; i++)
solve();
return 0;
}

T2

40分

双Hash暴力匹配…

100分

打标记,对于当前枚举串 $now$,从前往后扫。若扫到 $i$,$s_i$ 是 $s_j$ 的子串 $(i < j < now)$,我们就可以跳过不匹配 $i$。因为若 $s_i$ 不是 $s_{now}$ 的子串,则 $s_j$ 一定也不是 $s_{now}$ 的子串;若 $s_i$ 是 $s_{now}$ 的子串,$s_j$ 也有可能不是 $s_{now}$ 的子串。若不存在这样的 $j$,匹配即可,若 $s_i$ 是 $s_{now}$ 的子串,$i$ 之后就可以跳过了 (打个 $vis$ 标记);否则 $now$ 就可以更新答案,然后 $break$。

复杂度 $O(TNL)$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <bits/stdc++.h>
using namespace std;
inline void getNext(char *p, int m, int *next) {
for(register int i = 1, k = 0; i < m; i++) {
while(k && p[i] != p[k]) k = next[k - 1];
if(p[i] == p[k]) k++;
next[i] = k;
}
}
inline bool kmp(char *t, char *p, int n, int m, int *next) {
getNext(p, m, next);
for(register int i = 0, k = 0; i < n; i++) {
while(k && t[i] != p[k]) k = next[k - 1];
if(t[i] == p[k]) k++;
if(m == k) return true;
}
return false;
}
int t, n;
char s[510][2100];
int len[510], next[510][2100];
bool vis[510];
inline void solve() {
cin >> n;
register int ans = 0;
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++) {
cin >> s[i];
len[i] = strlen(s[i]);
for (int j = i - 1; j > 0; j--) {
if (vis[j]) continue;
if (kmp(s[i], s[j], len[i], len[j], next[i])) {
vis[j] = true;
} else {
ans = i;
break;
}
}
}
if (ans) cout << ans << "\n";
else cout << "-1\n";
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> t;
for (int i = 1; i <= t; i++)
solve();
return 0;
}

T3

首先可以很简单地想出 $O(n^6)$ 的 $dp$,然后我们可以简单优化成 $O(n^4)$,然后就能过了。
至于题解的 $O(n^3)$ 的玄学优化…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e17;
long long dp[127][127][127];
int n, a, b, c;
long long line[201], pre[201];
inline long long dfs(int x, int a1, int b1) {
if (~dp[x][a1][b1])
return dp[x][a1][b1];
register int c1 = pre[x - 1] - a1 - b1;
long long ret = 0;
if (x == n) return 1;
for (int i = 0; i <= line[x] && i <= a - a1; i++)
for (int j = 0; j <= b - b1 && j + i <= line[x]; j++)
if (line[x] - i - j <= c - c1)
ret = (ret + dfs(x + 1, a1 + i, b1 + j)) % mod;
dp[x][a1][b1] = ret;
return ret;
}
int main() {
memset(dp, -1, sizeof(dp));
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> a >> b >> c;
long long ans = 0, sum = a + b + c;
for (int i = 1; i <= n; i++)
cin >> line[i], pre[i] += pre[i - 1] + line[i], ans += line[i];
if (ans != sum)
cout << 0, exit(0);
cout << dfs(1, 0, 0);
return 0;
}

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×