1. 程式人生 > >【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer

【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer

con ifdef arc using 循環 ID graphs ans map

題解

考慮一個點雙(因為是簡單環),如果沒有環(兩點一線),那麽乘上K
如果有一個環,那麽用polya定理,每個置換圈有gcd(i,n)個循環節
如果有兩個及以上的環,任何一種置換都合法,那麽只和每個顏色用了多少個有關,用插板法算組合數就是\(\binom{n + k - 1}{k - 1}\)

代碼

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map> //#define ivorysi #define pb push_back #define space putchar(‘ ‘) #define enter putchar(‘\n‘) #define mp make_pair #define pb push_back #define fi first #define se second #define mo 974711 #define RG register #define MAXN 200005 using namespace std; typedef long long int64; typedef double
db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) f = -1; c = getchar(); } while(c >= ‘0‘ && c <= ‘9‘) { res = res * 10 + c - ‘0‘; c = getchar(); } res *= f; } template
<class T> void out(T x) { if(x < 0) {putchar(‘-‘);x = -x;} if(x >= 10) { out(x / 10); } putchar(‘0‘ + x % 10); } const int MOD = 1000000007; int N,M,K; struct node { int to,next; }E[1005]; int head[55],sumE,fac[205],invfac[205],dfn[55],low[55],idx,sta[105],top,col[55],cnt,ans; vector<int> ver; int mul(int a,int b) {return 1LL * a * b % MOD;} int inc(int a,int b) {a = a + b;if(a >= MOD) a -= MOD;return a;} int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } int gcd(int a,int b) { return b == 0 ? a : gcd(b,a % b); } void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } int C(int n,int m) { if(n < m) return 0; return mul(mul(fac[n],invfac[m]),invfac[n - m]); } void Tarjan(int u,int fa) { dfn[u] = low[u] = ++idx; sta[++top] = u; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa) { if(dfn[v]) low[u] = min(low[u],dfn[v]); else { Tarjan(v,u); if(low[v] >= dfn[u]) { ver.clear(); ++cnt; col[u] = cnt; ver.pb(u); while(1) { int x = sta[top--]; col[x] = cnt; ver.pb(x); if(x == v) break; } int tot = 0; for(auto k : ver) { for(int j = head[k] ; j ; j = E[j].next) { if(col[E[j].to] == cnt) ++tot; } } tot /= 2; if(tot == 1) ans = mul(ans,K); else if(tot == ver.size()) { int t = 0; for(int j = 1 ; j <= tot ; ++j) { t = inc(t,fpow(K,gcd(tot,j))); } t = mul(t,fpow(tot,MOD - 2)); ans = mul(ans,t); } else ans = mul(ans,C(tot + K - 1,K - 1)); } else low[u] = min(low[v],low[u]); } } } } void Solve() { read(N);read(M);read(K); int u,v; for(int i = 1 ;i <= M ; ++i) { read(u);read(v);add(u,v);add(v,u); } fac[0] = 1; for(int i = 1 ; i <= 200; ++i) fac[i] = mul(fac[i - 1],i); invfac[200] = fpow(fac[200],MOD - 2); for(int i = 199 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1); ans = 1; for(int i = 1 ; i <= N ; ++i) { if(!dfn[i]) Tarjan(i,0); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }

【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer