[UOJ UNR#2 UOJ拯救計劃]
阿新 • • 發佈:2017-09-02
using ble 二分 cst memset blank continue def pri
來自FallDream的博客,未經允許,請勿轉載,謝謝。
傳送門
感覺這題有點神...
模數是6比較奇怪,考慮計算答案的式子。
Ans=$\sum_{i=1}^{k} P(k,i)*ans(i)$ ans(i)表示恰好用i種顏色的方案數。
發現i<=2時候才有貢獻
i=1的時候,只有m=0才有貢獻,否則沒有
i=2的時候,判斷圖是否是二分圖,是的話答案就是2^(聯通塊個數)
#include<iostream> #include<cstring> #include<cstdio> #define MN 100000 usingnamespace std; inline int read() { int x=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar(); return x; } int sum; inline int pow(int x,int k) { for(sum=1;k;k>>=1,x=1LL*x*x%6) if(k&1) sum=1LL*sum*x%6; return sum; } int head[MN+5],vis[MN+5],cas,cnt,n,m,k,ans,col[MN+5]; struct edge{int to,next;}e[MN*4+5]; inline void ins(int f,int t) { e[++cnt]=(edge){t,head[f]};head[f]=cnt; e[++cnt]=(edge){f,head[t]};head[t]=cnt; } void Solve(int x) { vis[x]=cas;for(int i=head[x];i;i=e[i].next) if(vis[e[i].to]!=cas) col[e[i].to]=col[x]^1,Solve(e[i].to); else if(col[e[i].to]==col[x]) ans=0; } int main() { for(cas=read();cas;--cas) { n=read();m=read();k=read(); memset(head,0,sizeof(head));cnt=0;ans=1; for(int i=1;i<=m;++i) ins(read(),read()); if(!m) {printf("%d\n",pow(k,n));continue;} if(k==1||k%3!=2) {puts("0");continue;} for(int i=1;i<=n;++i) if(vis[i]!=cas) col[i]=0,Solve(i),ans=ans*2%6; printf("%d\n",ans); } return 0; }
[UOJ UNR#2 UOJ拯救計劃]