# SP8064 AMR10J-Mixing Chemicals

### SP8064 AMR10J - Mixing Chemicals

##### 算法一：dp

$$g_{i,j,k}$$表示考虑完前$$i$$个节点放的颜色，第$$i$$个节点颜色为$$j$$，第$$1$$个节点颜色为$$k$$的方案数，$$f_x=\sum\limits_{i\not=j}g_{x,i,j}$$

$$0$$代表相同，$$1$$代表不同，$$f_x=g_{x,0}$$ 朴素转移：

$\large g_{x,0}=g_{x-1,1},g_{x,1}=g_{x-1,0}\times(k-1)+g_{x-1,1}\times(k-2)$

$$\large f_{x+1}=f_{x-1}\times(k-1)+f_x\times(k-2)$$

$\large f_x=f_{x-1}\times(k-2)+f_{x-2}\times(k-1)$

##### 算法二：数学

$k^n=\sum_{i=0}^{n-2}{n\choose i}f_{n-i}+k$

$k^n=\sum_{i=2}^n{n\choose i}f_i+k$

$\large\sum_{i=0}^n{n\choose i}f_i=\begin{cases}1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~n=0\k^n-k+kn+1~~~~n>0 \end{cases}$

$$\large g_n=\sum\limits_{i=0}^n{n\choose i}f_i$$，那么

$\large f_n=\sum_{i=0}^n(-1)^{n-i}{n\choose i}g_i$

const int mod = 1e9 + 7,N = 105;
inline void write(int x) {
static int sta[64];
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
while (top) putchar(sta[--top] + 48); putchar(‘\n‘);
}
int mo(const int x){return x >= mod ? x-mod : x;}
int g[N],tot,ok[N],st[N],vis[N],c[N];
int dfs(int u){
if(vis[u]) return ok[u] ? -1 : vis[u];
st[++tot] = u; vis[u] = tot;
return dfs(c[u]);
}
int main(){
while(T--){
int n,k; g[0] = 1; g[1] = 0;
for(int i = 2;i <= n;++i)
g[i] = mo(1ll*g[i-1]*(k-2)%mod + 1ll*g[i-2]*(k-1)%mod);
for(int i = 0;i <= n;++i)
g[i] = 1ll*g[i]*k % mod;
for(int i = 1;i <= n;++i)
c[i] = read(),vis[i] = ok[i] = 0,++c[i];
int sum = n,ans = 1;
for(int i = 1;i <= n;++i){
if(!vis[i]){
tot = 0;int tmp = dfs(i);
for(int j = 1;j <= tot;++j)
ok[st[j]] = true;
if(~tmp){
tmp = tot - tmp + 1;sum -= tmp;
ans = 1ll*ans*g[tmp] % mod;
}
}
}
int sna = 1;
while(sum--)
sna = 1ll*sna*(k-1) % mod;
write(1ll*ans*sna%mod);
}
}


SP8064 AMR10J-Mixing Chemicals

(0)
(0)