1. 程式人生 > >[UOJ UNR#2 UOJ拯救計劃]

[UOJ UNR#2 UOJ拯救計劃]

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
using
namespace 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拯救計劃]