HDU5865 Stone game

来源:互联网 发布:深入浅出数据分析 微盘 编辑:程序博客网 时间:2024/06/05 12:02

传送门

Description

给定一幅n个节点m条边的DAG,有K个石子分布在一些节点上(可能有多个石子位于同一个节点),双方进行组合游戏,每次操作可以选择一个或两个石子,将它们分别移动一条边到达新的节点,不能操作者输.
求先手有多少种操作方案能够保证获得胜利.

n5,000,m105,K300.

Solution

比赛时联想到了NimK游戏,但是因为对其理解不够深刻导致没能写出来.
现在在这篇博客中关于NimK游戏添加了一些补充(如此张扬地刷访问量).

容易发现这题每个石子是独立的,并且每个节点的SG值可以很方便地O(n2+n+m)求出.
把每个石子看成一个子游戏,那么规则就变成了一次可以在最多两个子游戏中进行操作,这就是NimK游戏K=2时的一个特例了.

然后这题差不多就没了…求方案数时可以枚举移动的一个石子,用hash来求能够使得SG值二进制每一位上的数字和均为3的倍数的方案数.

总的复杂度…大概O(n2+(n+m)lgn)吧.

Code

写得比较丑..凭借极大的常数在HDU上暂列rank7.

#include <cmath>#include <ctime>#include <cctype>#include <cstdio>#include <cstring>#include <cstdlib>#include <cassert>#include <set>#include <map>#include <stack>#include <queue>#include <vector>#include <bitset>#include <complex>#include <iostream>#include <algorithm>#define fi first#define se second#define y1 jfskav#define pb push_back#define lson (k<<1)#define rson (k<<1|1)#define lowbit(x) (x&-x)#define debug(x) cout<<#x<<"="<<x<<endl#define rep(i,s,t) for(register int i=s,_t=t;i<_t;++i)#define per(i,s,t) for(register int i=t-1,_s=s;i>=_s;--i)using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;typedef double db;typedef pair<int,int> pii;typedef pair<ll,ll> pll;typedef vector<int> veci;const int mod=3,inf=0x7fffffff,rx[]={-1,0,1,0},ry[]={0,1,0,-1};const ll INF=1ll<<60;const db pi=acos(-1),eps=1e-6;template<class T>void rd(T &x){    x=0;    char c;    while(c=getchar(),c<48);    do x=(x<<3)+(x<<1)+(c^48);        while(c=getchar(),c>47);}template<class T>void rec_pt(T x){    if(!x)return;    rec_pt(x/10);    putchar(x%10^48);}template<class T>void pt(T x){    if(!x)putchar('0');    else rec_pt(x);}template<class T>inline void ptn(T x){    pt(x),putchar('\n');}template<class T>inline void Max(T &a,T b){    if(b>a)a=b;}template<class T>inline void Min(T &a,T b){    if(b<a)a=b;}template<class T>T gcd(T a,T b){    return b?gcd(b,a%b):a;}inline void mod_add(int &a,int b){    if((a+=b)>=mod)a-=mod;}inline void mod_minus(int &a,int b){    if((a-=b)<0)a+=mod;}const int N=(int)5e3+5,M=(int)1e5+5,MAX_K=305,LG=14,HASH=(int)1e7;int n,m,K,tot_edge,head[N],SG[N],pos[MAX_K],num[LG],tmp[LG],cnt[HASH],arr[M];bool mark[N];pii edge[M];void add_edge(int u,int v){    edge[tot_edge]=pii(v,head[u]);    head[u]=tot_edge++;}void calc_SG(int cur){    if(~SG[cur])return;    for(int i=head[cur];~i;i=edge[i].se)        calc_SG(edge[i].fi);    for(int i=head[cur];~i;i=edge[i].se)        mark[SG[edge[i].fi]]=true;    for(SG[cur]=0;mark[SG[cur]];++SG[cur]);    for(int i=head[cur];~i;i=edge[i].se)        mark[SG[edge[i].fi]]=false;}bool check(){    rep(i,0,LG)if(num[i])return false;    return true;}int Hash(){    int res=0;    for(int i=0,pw=1;i<LG;++i,pw*=mod)res+=tmp[i]*pw;    return res;}void solve(){    rd(m),rd(K);    tot_edge=0;    memset(head,-1,n+1<<2);    memset(SG,-1,n+1<<2);    for(int u,v;m--;){        rd(u),rd(v);        add_edge(u,v);    }    rep(i,0,K)rd(pos[i]);    rep(i,1,n+1)calc_SG(i);    rep(i,0,LG){        num[i]=0;        rep(j,0,K)mod_add(num[i],SG[pos[j]]>>i&1);    }    int ans=0;    cnt[0]=1;    rep(i,0,K){        int tot=0;        for(int j=head[pos[i]];~j;j=edge[j].se){            int to=edge[j].fi;            // putchar('\n');//            // debug(pos[i]),debug(to);//            rep(k,0,LG){                mod_minus(tmp[k]=0,SG[pos[i]]>>k&1);                mod_add(tmp[k],SG[to]>>k&1);                // debug(k),debug(tmp[k]);//            }            arr[tot++]=Hash();            // putchar('\n');//            rep(k,0,LG){                if(tmp[k])tmp[k]=mod-tmp[k];                mod_minus(tmp[k],num[k]);                // debug(k),debug(tmp[k]);//            }            ans+=cnt[Hash()];        }        rep(j,0,tot)++cnt[arr[j]];    }    rep(i,0,K)for(int j=head[pos[i]];~j;j=edge[j].se){        int to=edge[j].fi;        rep(k,0,LG){            mod_minus(tmp[k]=0,SG[pos[i]]>>k&1);            mod_add(tmp[k],SG[to]>>k&1);        }        cnt[Hash()]=0;    }    ptn(ans);}int main(){    while(~scanf("%d",&n))solve();    return 0;}/*    Aug.19.16    Tags:game theory    Submissions:2    Exe.Time 577MS    Exe.Memory 2496K    Code Len. 3527B*/
0 0
原创粉丝点击