「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:天才绅士少女助手克里斯蒂娜

化简式子,可以直接改成区间求和的形式。

a n s = i = l r j = i + 1 r ( x i 2 y j 2 + x j 2 y i 2 2 x i y i x j y j ) = i = l r j = i + 1 r x i 2 y j 2 + i = l r j = i + 1 r x j 2 y i 2 i = l r j = i + 1 r 2 x i y i x j y j = i = l r j = l r [ i ! = j ] × x i 2 y j 2 i = l r j = l r [ i ! = j ] × x i y i x j y j = i = l r x i 2 ( j = l r y j 2 y i 2 ) ( i = l r x i y i ( j = l r x j y j x i y i ) ) = i = l r x i 2 j = l r y j 2 i = l r x i 2 y i 2 ( i = l r x i y i j = l r x j y j i = l r x i 2 y i 2 ) = i = l r x i 2 × i = l r y i 2 ( i = l r x i y i ) 2

树状数组维护一下就好了。

#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);

}
posted @ 2020-10-17 12:07  hyskr  阅读(81)  评论(0编辑  收藏  举报