[dp] Jzoj P3460 Mixing Chemicals

Description

实验室有n瓶化学药品,编号为0到n-1,你知道第i瓶只有和第c[i]瓶放在一起才会发生爆炸。为了整理实验室,你需要将他们装进k个丌同的盒子里。显然,为了你的生命安全,你丌能把两瓶会造成爆炸的药品放进同一个箱子。你希望计算出有多少中丌同的方案。为了降低难度,你只需要将答案mod 1000000007。
 

Input

第一行一个整数T,表示有T组测试数据。

对于每组数据

第一行两个整数n,k

第二行n个整数表示c[i]

Output

对于每组数据输出一行一个整数。
 

Sample Input

3
3 3
1 2 0
4 3
1 2 0 0
3 2
1 2 0

Sample Output

6
12
0
 

Data Constraint

1<=T<=50 1<=n<=100 2<=k<=1000 0<Ci <n ,i≠c[i]

对于30%的数据T,n,k<=50

 

题解

  • 题目大意:给n瓶化学药品和k个盒子,每瓶化学药品和一瓶化学药品不能放在一个盒子里,求放化学药品的方案数
  • 我们可以将不能放在同一个盒子的两瓶化学药品连一条边,那么就形成了一个图,而且每个点的出都只有1
  • 那么考虑一下染色,一条边的两个点不能染成同一种颜色
  • 其实这样的话,就可以设f[i][0/1]为第i个点,染0色或1色的方案数
  • f[i][0]=(f[i-1][1]*(k-1)+f[i-1][0]*(k-2))%mo
  • f[i][1]=f[i][0]
  • 这个可以预处理出来
  • 然后我们将每个点在哪个环求出来,在求出连通块的个数,然后ans=ans* (f[lt,1]*k%mo)%mo lt为当前循环的搜到的连通块的个数
  • 求出将每个连通块的填颜色的个数相乘就求出ans

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 const int inf=1000000000,mo=1000000007;
 6 long long ans,a[110],d[110],tot,num,f[110][3];
 7 int n,k,t;
 8 int main()
 9 {
10     for (scanf("%d",&t);t;t--)
11     {
12         memset(a,0,sizeof(a)); memset(d,0,sizeof(d)); memset(f,0,sizeof(f));
13         scanf("%d%d",&n,&k);
14         for (int i=0;i<=n-1;i++) 
15         {
16             scanf("%lld",&a[i]);
17             d[i]=inf;
18         }
19         f[0][1]=1; f[1][0]=k-1;
20         for (int i=2;i<=n;i++)
21         {
22             f[i][0]=(f[i-1][1]*(k-1)+f[i-1][0]*(k-2))%mo;
23             f[i][1]=f[i-1][0];
24         }
25         num=0; ans=1;
26         for (int i=0;i<=n-1;i++)
27             if (d[i]==inf)
28             {
29                 int x=i;
30                 while (d[x]==inf) d[x]=i,x=a[x];
31                 if (d[x]!=i) continue;
32                 int y=x; tot=1; x=a[x];
33                 while (x!=y) tot++,x=a[x];
34                 ans=ans*(f[tot][1]*k%mo)%mo;
35                 n-=tot;
36             }
37         for (int i=1;i<=n;i++) (ans*=(k-1))%=mo;
38         printf("%lld\n",ans);
39     }
40 }

 

posted @ 2018-07-18 16:01  BEYang_Z  阅读(230)  评论(0编辑  收藏  举报