1. 程式人生 > >2018.10.25 uoj#308. 【UNR #2】UOJ拯救計劃(排列組合)

2018.10.25 uoj#308. 【UNR #2】UOJ拯救計劃(排列組合)

傳送門 有一個顯然的式子:Ans=A(n,i)iAns=\sum A(n,i)*用i種顏色的方案數 這個東西貌似是個NPCNPC。 於是需要仔細觀察資料範圍。 咦模數等於66? 那麼對於A(n,i)A(n,i)i3i\geq 3的時候模66都是00了。 因此只用討論i=1i=1i=2i=2的方案數。 什麼? i=1?i=1? 沒錯,題目上並沒有說過m!=0m!=0啊。 還有就是貌似邊數跟題目描述不太一樣。 程式碼:

#include<bits/stdc++.h>
using
namespace std; inline int read(){ int ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } const int N=1e5+5,M=2e6+5,mod=6; int T,n,m,K,first[N],cnt=0,tot=0,fa[N],col[N],ans; struct edge{int v,next;}e[M<<
1]; inline void addedge(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;} inline void add(int u,int v){addedge(u,v),addedge(v,u);} inline bool dfs(int p,int f){ col[p]=f; for(int i=first[p];i;i=e[i].next){ int v=e[i].v; if(~col[v]){if(!(col[v]^f))return false;} else if(!dfs(v,f^1
))return false; } return true; } inline int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);} int main(){ T=read(); while(T--){ n=read(),m=read(),K=read(); if(!m){ ans=1; for(int i=1;i<n;++i){ ans<<=1; if(ans>=mod)ans-=mod; } --ans; if(ans<0)ans+=mod; ans=ans*K%mod*(K-1)%mod; ans+=K%mod; if(ans>=mod)ans-=mod; } else{ cnt=0,tot=0,ans=1; for(int i=1;i<=n;++i)first[i]=0,fa[i]=i,col[i]=-1; for(int i=1,u,v,fx,fy;i<=m;++i){ u=read(),v=read(),add(u,v),add(v,u),fx=find(u),fy=find(v); if(fx!=fy)fa[fx]=fy; } for(int i=1,f;i<=n;++i) if(~col[i])continue; else{ if(!dfs(i,0)){ans=0;break;} ++tot; } if(ans){ for(int i=1;i<tot;++i){ ans<<=1; if(ans>=mod)ans-=mod; } ans=ans*K%mod*(K-1)%mod; } } printf("%d\n",ans); } return 0; }