1. 程式人生 > >Codechef :A Game of Thrones/GTHRONES(網路流)

Codechef :A Game of Thrones/GTHRONES(網路流)

傳送門

題解: 用Miller-Rabin建邊,之後就是個二分圖博弈。

這個直接判斷最大匹配的必備點即可,注意每個點可以匹配多次,可以用網路流退流來判斷。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return
(ib==ob) ? -1 : *ib++; } template <typename T> inline void rd(T &x) { char ch=nc(); T i=0,f=1; while(!isdigit(ch)) {if(ch=='-') f=-1; ch=nc();} while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();} x=i*f; } const int N=1e5+50, M=2e6+50, inf=0x3f3f3f3f; const int pr[]={2,3,5,7,
11,13,17,19}; int n,b[N],col[N],vis[N],tar[N],win[N]; LL a[N]; vector <int> e[N]; inline LL mul(LL a,LL b,LL mod) {return (a*b-(LL)((long double)a/mod*b+1e-4)*mod+mod)%mod;} inline LL power(LL a,LL b,LL mod,LL rs=1) {for(;b;b>>=1,a=mul(a,a,mod)) if(b&1) rs=mul(rs,a,mod); return rs;} namespace
mcmf { int g[N],nt[M],vt[M],c[M],ec=1; int lev[N],cur[N],q[N],src,des; inline void add(int x,int y,int cc) { nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; c[ec]=cc; nt[++ec]=g[y]; g[y]=ec; vt[ec]=x; c[ec]=0; } inline bool bfs() { for(int i=1;i<=des;i++) lev[i]=0; int r; q[r=1]=src; lev[src]=1; for(int i=1;i<=r;i++) { int u=q[i]; for(int e=g[u];e;e=nt[e]) if(c[e] && (!lev[vt[e]])) { lev[vt[e]]=lev[u]+1; q[++r]=vt[e]; if(vt[e]==des) return true; } } return false; } inline int dinic(int x,int f) { if(x==des) return f; int rs=0; for(int &e=cur[x];e;e=nt[e]) { if(!c[e] || (lev[vt[e]]!=lev[x]+1)) continue; int o=dinic(vt[e],min(f-rs,c[e])); c[e]-=o; c[e^1]+=o; rs+=o; if(rs==f) return rs; } return lev[x]=0, rs; } inline void maxflow() { while(bfs()) { int rs; memcpy(cur+1,g+1,sizeof(int)*des); while((rs=dinic(src,inf))) memcpy(cur+1,g+1,sizeof(int)*des); } } } inline void dfs(int x,int c) { col[x]=c; vis[x]=1; for(auto v:e[x]) if(!vis[v]) dfs(v,c^1); } inline bool MR(LL t) { if(t==1) return false; if(t<=3) return true; if((t%6)!=1 && (t%6)!=5) return false; LL s1=0, s2=t-1; while(!(s2&1)) s1++, s2>>=1; for(int i=0;i<=7;i++) { if(t==pr[i]) return true; LL v=power(pr[i],s2,t); for(int j=1;v!=1 && j<=s1;j++) { LL v2=mul(v,v,t); if(v2==1 && (v!=1 && v!=t-1)) return false; v=v2; } if(v!=1) return false; } return true; } inline bool check(LL a,LL b) { if(a<b) swap(a,b); if(a%b) return false; return MR(a/b); } int main() { rd(n); for(int i=1;i<=n;i++) rd(a[i]), rd(b[i]); mcmf::src=n+1; mcmf::des=n+2; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(check(a[i],a[j])) e[i].push_back(j), e[j].push_back(i); for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,0); for(int i=1;i<=n;i++) for(auto v:e[i]) if(i<v) if(col[i]) mcmf::add(v,i,inf); else mcmf::add(i,v,inf); for(int i=1;i<=n;i++) if(col[i]) mcmf::add(i,mcmf::des,b[i]), tar[i]=mcmf::ec-1; else mcmf::add(mcmf::src,i,b[i]), tar[i]=mcmf::ec-1; mcmf::maxflow(); for(int i=1;i<=n;i++) if(!mcmf::c[tar[i]]) { static int q[N],r; r=0; for(int e=mcmf::g[i];e;e=mcmf::nt[e]) { int v=mcmf::vt[e]; if(v<=n && mcmf::c[e|1]) q[++r]=tar[v]; } for(int j=1;j<=r;j++) ++mcmf::c[q[j]]; if(!mcmf::bfs()) win[i]=1; for(int j=1;j<=r;j++) --mcmf::c[q[j]]; } LL ans=2e18; for(int i=1;i<=n;i++) if(!win[i]) ans=min(ans,a[i]); if(ans!=2e18) printf("Bran %lld\n",ans); else puts("Tyrion"); }