「csp模拟」模拟测试15
T1:游戏
- 即 [Scoi2010]游戏 或 [BZOJ1854] 连续攻击游
- 二分图求解,有一个二分图的优化,由于每次
memset
一边非常耗费时间,需要优化。
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int k = 0, f = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
return k * f;
}
const int maxn = 2e6 + 100, maxm = 1e6 + 100;
struct node { int to, next; } e[maxn];
int ecnt = 0, head[maxn];
void add(int u, int v) { e[++ecnt] = (node){v, head[u]}; head[u] = ecnt; }
int vis[maxm], match[maxn], t;
int find(register int u) {
vis[u] = t;
for (register int i = head[u]; i; i = e[i].next) {
register int v = e[i].to;
if (vis[v] == t) continue;
vis[v]++;
if (match[v] == 0 || find(match[v])) {
match[v] = u;
return 1;
}
}
return 0;
}
int main() {
freopen("game.in", "r", stdin), freopen("game.out", "w", stdout);
register int n = read(), x, y;
for (register int i = 1; i <= n; i++) {
x = read(), y = read();
add(x, i + n), add(y, i + n);
}
register int cnt = 0;
for (register int i = 1; i <= n; i++) {
t = i;
if (find(i)) cnt++;
else break;
}
printf("%d\n", cnt);
}
T2:嘟嘟噜
约瑟夫游戏,递推公式\(\text{f[i + 1] = (f[i] + m) % i}\) ,观察本题的特殊性质: m 远小于 n,再看递推公式,发现当m很小的时候取模次数并不多,所以在这种情况下可以直接用一次乘法代替多次加法。
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
int k = 0, f = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
return k * f;
}
const int maxn = 4e6 + 100;
signed main() {
freopen("mayuri.in", "r", stdin), freopen("mayuri.out", "w", stdout);
register int T = read();
while (T--) {
register int n = read(), m = read(), now = 1;
for (register int i = 1; i <= n; i++) {
now = now + m;
int jump = (i - now) / m - 1;
jump = min(n - i - 1, jump);
if (jump > 0 && jump < n) {
now += jump * m;
i += jump;
}
now %= i;
if (now == 0) now == i;
}
printf("%lld\n", now + 1);
}
return 0;
}
T3:天才绅士少女助手克里斯蒂娜
化简式子,可以直接改成区间求和的形式。
树状数组维护一下就好了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
int k = 0, f = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
return k * f;
}
const int mod = 20170927, maxn = 1e6 + 100;;
int w1[maxn], w2[maxn], w3[maxn], n, q;
int ax[maxn], ay[maxn];
int lowbit(int x) { return x & -x; }
void add1(int x, int val) { for (; x <= n; x += lowbit(x)) (w1[x] += val) %= mod; }
int query1(int x) { int ans = 0; for (; x; x -= lowbit(x)) (ans += w1[x]) %= mod; return ans % mod; }
void add2(int x, int val) { for (; x <= n; x += lowbit(x)) (w2[x] += val) %= mod; }
int query2(int x) { int ans = 0; for (; x; x -= lowbit(x)) (ans += w2[x]) %= mod; return ans % mod; }
void add3(int x, int val) { for (; x <= n; x += lowbit(x)) (w3[x] += val) %= mod; }
int query3(int x) { int ans = 0; for (; x; x -= lowbit(x)) (ans += w3[x]) %= mod; return ans % mod; }
signed main() {
freopen("kurisu.in", "r", stdin), freopen("kurisu.out", "w", stdout);
n = read(), q = read();
for (int i = 1; i <= n; i++) {
int x = read(), y = read();
ax[i] = x, ay[i] = y;
add1(i, x * x % mod), add2(i, y * y % mod), add3(i, x * y % mod);
}
for (int i = 1; i <= q; i++) {
int opt = read();
if (opt == 2) {
int l = read(), r = read();
int x1 = (query1(r) - query1(l - 1) + mod) % mod;
int x2 = (query2(r) - query2(l - 1) + mod) % mod;
int x3 = (query3(r) - query3(l - 1) + mod) % mod;
printf("%lld\n", (x1 * x2 % mod - x3 * x3 % mod + mod) % mod);
} else {
int pos = read(), x = read(), y = read();
add1(pos, (x * x % mod - ax[pos] * ax[pos] % mod + mod) % mod);
add2(pos, (y * y % mod - ay[pos] * ay[pos] % mod + mod) % mod);
add3(pos, (x * y % mod - ax[pos] * ay[pos] % mod + mod) % mod);
ax[pos] = x, ay[pos] = y;
}
}
}
T4:凤凰院凶真
- LCIS板子题,没啥可说的,考试时调出了长度,没看到要输出路径,,,
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int k = 0, f = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
return k * f;
}
#define int long long
const int maxn = 5e3 + 10;
int a[maxn], b[maxn], f[maxn][maxn], pre[maxn][maxn];
void print(int n, int x) {
if (!n) return ;
print(n - 1, pre[n][x]);
if (pre[n][x] != x) printf("%lld ", b[x]);
}
signed main() {
freopen("phoenix.in", "r", stdin); freopen("phoenix.out", "w", stdout);
int n = read();
for (int i = 1; i <= n; i++) a[i] = read();
int m = read();
for (int i = 1; i <= m; i++) b[i] = read();
int cnt = 0, ans = 0, last = 0;
int maxr = 0;
for (int i = 1; i <= n; i++) {
int k = 0, maxx = 0;
for (int j = 1; j <= m; j++) {
if (a[i] == b[j]) f[i][j] = maxx + 1, pre[i][j] = k;
else f[i][j] = f[i - 1][j], pre[i][j] = j;
if (a[i] > b[j] && f[i][j] > maxx) maxx = f[i][j], k = j;
}
}
for (int i = 1; i <= n; i++)
if (f[n][i] > f[n][maxr]) {
maxr = i;
ans = f[n][i];
}
printf("%lld\n", ans);
if (ans == 0) return !puts("0");
print(n, maxr);
}