生活随笔
收集整理的這篇文章主要介紹了
Problem B: 故障电灯(light)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- 考慮對電燈進行差分:若第i個電燈和第i + 1個電燈狀態不同,則在第i個位置上放一個球
這樣我們就放置了不超過2n個球,且必然是偶數個
于是問題轉化為:有m個球,每一步可以把一個球平移奇質數個位置,兩個球位于相同位置則同時被消除,計算至
少多少步能消除所有球 - 然后我們發現, 假如兩個東西距離為奇質數cost為1, 偶數cost為二(哥德巴赫猜想), 其余奇數的話cost為3
- 然后發現一種貪心方法, 是盡量匹配cost為1的, 然后分奇偶性各自用2覆蓋,看看最后剩下的那個直接判斷即可
-
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#define ll long long
#define mmp make_pair
#define M
using namespace std;
int read() {int nm = 0, f = 1;char c = getchar();for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';return nm * f;
}
struct Edge{int v, c, nxt;
}e[200010];
int head[10010], tot = 1;
void build(int u, int v, int c)
{e[++tot] = (Edge){v, c, head[u]}; head[u] = tot; return ;
}
void insert(int u, int v, int c)
{build(u, v, c); build(v, u, 0); return ;
}
int dep[10010];
int S, T;
queue<int> q;
bool bfs()
{memset(dep, 0, sizeof(dep)); dep[S] = 1; q.push(S); while(!q.empty()){int u = q.front(); q.pop(); for(int i = head[u]; i; i = e[i].nxt)if(!dep[e[i].v]&&e[i].c){dep[e[i].v] = dep[u] + 1; q.push(e[i].v); }}if(dep[T])return true; return false;
}
int cur[10010];
int dfs(int u, int flow)
{if(u == T)return flow; for(int &i = cur[u]; i; i = e[i].nxt)if(e[i].c&&dep[e[i].v] == dep[u] + 1){int d = dfs(e[i].v, min(e[i].c, flow)); if(d){e[i].c -= d; e[i^1].c += d; return d; }}return 0;
}
int dinic()
{int ans = 0; while(bfs()){for(int i = S; i <= T; i++)cur[i] = head[i]; int d; while(d = dfs(S, 1e9))ans += d; }return ans;
}
int prime[1000010], cnt;
bool vis[10000010];
int x[1010];
int posx[1010], posy[1010];
int cnt1, cnt2;
void push(int x)
{if(x&1)posx[++cnt1] = x; else posy[++cnt2] = x;
}
int main(){int N = 10000000; vis[1] = true; for(int i = 2; i <= N; i++){if(!vis[i])prime[++cnt] = i; for(int j = 1; j <= cnt&&i * prime[j] <= N; j++){vis[i * prime[j]] = true; if(i%prime[j] == 0)break; }}vis[2] = true; int t = read();while(t--){memset(head, 0, sizeof(head)); cnt1 = cnt2 = 0; tot = 1; int n = read();for(int i = 1; i <= n; i++){x[i] = read(); if(i == 1||x[i - 1] != x[i] - 1)push(x[i]); if(i> 1&&x[i - 1] != x[i] - 1)push(x[i - 1] + 1); }push(x[n] + 1); S = 0, T = cnt1 + cnt2 + 1; for(int i = 1; i <= cnt1; i++)insert(S, i, 1); for(int i = 1; i <= cnt1; i++)for(int j = 1; j <= cnt2; j++)if(!vis[max(posx[i] - posy[j], posy[j] - posx[i])])insert(i, cnt1 + j, 1); for(int i = 1; i <= cnt2; i++)insert(cnt1 + i, T, 1); int ans = dinic(); printf("%d\n", ans + (cnt1 - ans)/2 * 2 + (cnt2 - ans)/2 * 2 + (cnt1 - ans)%2 * 3); }return 0;
}
轉載于:https://www.cnblogs.com/luoyibujue/p/10719689.html
總結
以上是生活随笔為你收集整理的Problem B: 故障电灯(light)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。