日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

AT2689 [ARC080D] Prime Flip

發(fā)布時間:2023/12/13 综合教程 34 生活家
生活随笔 收集整理的這篇文章主要介紹了 AT2689 [ARC080D] Prime Flip 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

簡要題解如下:

區(qū)間修改問題,使用差分轉(zhuǎn)化為單點(diǎn)問題。

問題變成,一開始有 (2n) 個點(diǎn)為 (1),每次操作可以選擇 (r - l) 為奇質(zhì)數(shù)的兩個點(diǎn) (l, r) 使其 ^ (1)。

根據(jù)哥德巴赫猜想可以發(fā)現(xiàn),若 (r - l) 為奇質(zhì)數(shù)顯然一次即可,若 (r - l) 為偶數(shù)則需兩次,若 (r - l) 為奇數(shù)則需三次。

近一步可以發(fā)現(xiàn),若想消去兩個點(diǎn) (l, r) 則涉及其他點(diǎn)是可以通過調(diào)整使得直接消去兩個點(diǎn)的。

更近一步可以發(fā)現(xiàn),將所有點(diǎn)按照奇偶分類,顯然若消去奇偶性相同的兩個數(shù)只能 (2) 次,那么首先將差是奇質(zhì)數(shù)的點(diǎn)一起消去肯定是最優(yōu)的。

因?yàn)椴钍瞧尜|(zhì)數(shù)的點(diǎn)必然一個為偶數(shù)一個為奇數(shù)構(gòu)成二分圖,于是可以使用匈牙利或網(wǎng)絡(luò)流解決二分圖最大匹配問題。

剩下的肯定要同集合內(nèi)部按照 (2) 次消去,最后若還剩一個元素才使用 (3) 次的方法。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define Next(i, u) for (int i = cur[u]; i; i = e[i].next)
const int N = 2e4 + 5;
const int M = 1e7 + 5;
struct edge { int v, next, w;} e[N << 1];
int n, s, t, F, ans, cnt, tot = 1, ton[2], a[N], h[N], d[M];
namespace PR {
    bool iprime[M]; int tot, prime[M];
    void sieve(int L) {
        iprime[1] = 1;
        rep(i, 2, L) {
            if(!iprime[i]) prime[++tot] = i;
            for (int j = 1; j <= tot && i * prime[j] <= L; ++j) {
                iprime[i * prime[j]] = true;
                if(i % prime[j] == 0) break;
            }
        }
    }
}
namespace FL {
    bool book[N]; int dep[N], cur[N];
    bool bfs(int s, int t) {
        rep(i, s, t) cur[i] = h[i], dep[i] = -t;
        queue <int> Q;
        dep[s] = 1, Q.push(s);
        while (!Q.empty()) {
            int u = Q.front(); Q.pop();
            Next(i, u) {
                int v = e[i].v; if(!e[i].w || dep[v] > 0) continue;
                dep[v] = dep[u] + 1, Q.push(v);
            }
        }
        return dep[t] > 0;
    }
    int dfs(int u, int lim) {
        if(u == t) return lim;
        int flow = 0, rflow = 0; book[u] = true;
        Next(i, u) {
            int v = e[i].v; cur[u] = i;
            if(!book[v] && dep[v] == dep[u] + 1 && e[i].w && (rflow = dfs(v, min(e[i].w, lim)))) {
                flow += rflow, lim -= rflow, e[i].w -= rflow, e[i ^ 1].w += rflow;
                if(!lim) break;
            }
        }
        book[u] = false; return flow;
    }
}
void add(int u, int v, int w) {
    e[++tot].v = v, e[tot].w = w, e[tot].next = h[u], h[u] = tot;
    e[++tot].v = u, e[tot].w = 0, e[tot].next = h[v], h[v] = tot;
}
int main () {
    cin >> n;
    rep(i, 1, n) cin >> a[i], d[a[i]] ^= 1, d[a[i] + 1] ^= 1;
    PR :: sieve(M - 1);
    s = cnt = 1;
    rep(i, 1, M - 1) if(d[i]) a[++cnt] = i, ++ton[i & 1];
    t = ++cnt;
    rep(i, 2, cnt - 1) {
        if(a[i] & 1) add(s, i, 1);
        else add(i, t, 1);
    }
    rep(i, 2, cnt - 1) if(a[i] & 1) {
        rep(j, 2, cnt - 1) if(!(a[j] & 1) && !(PR :: iprime[abs(a[j] - a[i])])) add(i, j, 1);
    }
    while (FL :: bfs(s, t)) ans += FL :: dfs(s, cnt);
    if((ton[0] - ans) & 1) F = 1;
    ans += 2 * ((ton[0] - ans) / 2 + (ton[1] - ans) / 2);
    ans += F * 3;
    printf("%d", ans);
    return 0;
}

首先區(qū)間修改差分轉(zhuǎn)單點(diǎn)是非常重要的,可以減少有效修改點(diǎn)數(shù),方便于觀察問題。

對于某個數(shù)能被質(zhì)數(shù) / 奇質(zhì)數(shù)組成的問題,一定要敏銳地想到 哥德巴赫猜想

總結(jié)

以上是生活随笔為你收集整理的AT2689 [ARC080D] Prime Flip的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。