牛客挑战赛49

牛客挑战赛49

tjc的签到

ll ans = -1, w = 0;

int main() {
    IOS; map<int, int> st;
    cin >> n;
    rep (i, 1, n) cin >> m, ++st[m];
    for (auto &i : st) if (umax(ans, (ll)i.fi * i.se)) w = i.fi;
    cout << ans;
    return 0;
}

tjc与sweet

不考虑进位, 则每相邻10个数贡献为9(因为计数从2卡开始, 最后答案减去 0->1 的贡献)

在考虑进位, 对于10进位是 9 - 1

对于百位进位是 9 * 2 - 1

...

然后拆位统计即可

char s[N];
ll ans = -1, c = 9;

int main() {
    IOS; cin >> s + 1; n = strlen(s + 1);
    if (n == 1 && s[1] == '1') return cout << 0, 0;
    ans += s[n] ^ '0';
    for (int i = n - 1, j = 2; i; --i, ++j) {
        ans = (ans + (s[i] ^ '0') * c % mod) % mod;
        ll cur = (j - 1) * 9 - 1;
        ans = (ans + cur * (s[i] ^ '0')) % mod;
        c = (c * 10 % mod + 9 * cur % mod);
    }
    cout << ans;
    return 0;
}

alan的DP题

很容易想到(nlogn)的可惜t飞

那只能像线性了

那就从大到小, 看 i 能不能被选呗, 并查集爬树 (O(n))

要用快读, 不然还是会t, 离谱, 1202年还有卡关同步的 cin 的

int fa[N], f[N], c[N];
ll ans;

int ff(int x) { return x == f[x] ? x : f[x] = ff(f[x]); }

int main() {
    read(n, m);
    rep (i, 1, n) read(fa[i]), f[i] = i;
    rep (i, 1, m) read(k), ++c[k];
    per (i, n, 1) {
        int x = ff(i);
        while (x && !c[x]) f[x] = fa[x], x = fa[x];
        if (c[x]) ans += i, --c[x];
    }
    write(ans);
    return 0;
}

alan的字符串

对于串s, t分别建立其正反的序列自动机, 爆搜

int nts[N][2][26], ntt[45][2][26], ls[26];
char s[N], t[45];

void init(char *s, int n, int nt[][2][26]) {
    memset(ls, -1, sizeof ls);
    per (i, n, 0) {
        rep (j, 0, 25) nt[i][0][j] = ls[j];
        if (i) ls[s[i] - 'a'] = i;
    }
    memset(ls, -1, sizeof ls);
    rep (i, 1, n + 1) {
        rep (j, 0, 25) nt[i][1][j] = ls[j];
        if (i <= n) ls[s[i] - 'a'] = i;
    }
}

void dfs(int ls, int rs, int lt, int rt, int len) {
    if (min(ls, rt) == -1 || min(lt, rt) == -1) return;
    if (ls >= rs || lt >= rt) {
        if (ls > rs || lt > rt) umax(k, len - 2);
        else if (ls == rs || lt == rt) umax(k, len - 1);
        return;
    }
    rep (i, 0, 25) dfs(nts[ls][0][i], nts[rs][1][i], ntt[lt][0][i], ntt[rt][1][i], len + 2);
}

int main() {
    IOS; cin >> s + 1 >> t + 1;
    init(s, n = strlen(s + 1), nts); init(t, m = strlen(t + 1), ntt);
    dfs(0, n + 1, 0, m + 1, 0);
    cout << k;
    return 0;
}

东兴保卫战

必须选完所有点, 故问题可以转换为, 两个的获得的边数最多,

毕竟点数确定了, 获得的边数越多, 则连通块越少

则对点按照度数排序即可, 贪心取

int deg[N];

int main() {
    IOS; cin >> n; int x[2] = { 0, 0 };
    rep (i, 2, n) {
        int u, v; cin >> u >> v;
        ++deg[u], ++deg[v];
    }
    sort(deg + 1, deg + 1 + n);
    rep (i, 1, n) x[i & 1] += deg[i];
    cout << ((n + 1 >> 1) - (x[1] >> 1) - (n >> 1) + (x[0] >> 1));
    return 0;
}

alan的图

不是简单路径, 则可以从路径上任意一个点, 到另一个点再回来, 则可以替换路径上任意一个点

也可以选两个点(x, y), 则路径上任意一点到x回来, 再去y回来, 则路径增加两个点(x, y)

则变成了路径上要么加两个点, 要么替换一个点,

这张图为联通二分图, 两点之间可以任意到达, 则变为了, 从整张图中选点异或值最大权值问题

二分图则是同侧路径点为奇数, 异侧点路径点数为偶数

直接线性基, 然后用个小技巧

在添加每个点权值的时候都异或一个娶不到的权值(1 << 30)

再求奇数个数异或最大值的时候直接询问 askmx(1 << 30), 偶数则问 askmx(0) 即可

贪心的保证选点的奇偶性

struct XXJ {
    int g[31], mx[2];
    void insert(int x) {
        per (i, 30, 0) if (x >> i & 1)
            if (!g[i]) { g[i] = x; return; }
            else x ^= g[i];
    }
    void askmx() { 
        mx[0] = K;
        per (i, 30, 0) umax(mx[1], mx[1] ^ g[i]), umax(mx[0], mx[0] ^ g[i]);
        mx[1] ^= K, mx[0] ^= K;
    }
} xxj;

int n, m, _, k, cas;
int bas, x, y, las;
int c[N];
VI h[N];
ll ans = 0;

void dfs(int x, int col) {
    c[x] = col;
    for (auto &y : h[x]) if (!c[y]) dfs(y, 3 - col);
}

int main() {
    IOS; cin >> n >> m >> k >> bas >> x >> y;
    rep (i, 1, n) cin >> _, xxj.insert(_ ^ K);
    rep (i, 1, m) { int u, v; h[u].pb(v); h[v].pb(u); }
    dfs(1, 1); xxj.askmx();
    rep (i, 1, k) {
        x = ((ll)x * bas + las) % n + 1, y = ((ll)y * bas + las) % n + 1;
        las = xxj.mx[c[x] ^ c[y]];
        ans += las;
    }
    cout << ans;
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14671621.html