luogu P6239 奇怪的道路

奇怪的道路

我看不出来是状压的状压。

好吧,其实看到k的范围应该去往状压方面想的。

然后,题目中说“任何一个城市都与恰好偶数条道路相连(0也被认为是偶数)”。

所以,奇偶,两种状态可以用0,1来表示,那就妥妥的状压了。

设\(dp_{i,j,sta}\)表示当前已经考虑了i座城市,j条道路,当前状态为sta的方案数。

用0表示奇数,1表示偶数,为了防止转移时出现问题,所以只转移第i个城市的前k个城市,通过异或能够将连边的两个城市由奇变偶,由偶变奇。

则有

\[dp_{i,j,sta}=\sum_{i-k\le l<i}^{0\le sta< 2^{k+1}}dp_{i,j-1,sta^{\wedge}1^{\wedge}2^{i-l}} \]

因为在转移的时候,sta表示的范围在发生变化,所以对于每一个i都要再单独处理一下

\[dp_{i+1,j,sta\times2}=\sum_{0\le j\le m}^{0\le sta<2^{k}}dp_{i,j,sta} \]

Code:

#include<cstdio>
#define top 10
#define MAX 32
#define re register
namespace OMA
{
   int n,m,k;
   int dp[MAX][MAX][1<<top];
   const int p=1000000007;
   inline int max(int a,int b)
   { return a>b?a:b; }
   signed main()
   {
     scanf("%d%d%d",&n,&m,&k);
     dp[2][0][0] = 1;
     for(re int i=2; i<=n; i++)
     {
       for(re int l=max(i-k,1); l<=i-1; l++)
       {
         for(re int j=1; j<=m; j++)
         {
           for(re int temp=0; temp<(1<<k+1); temp++)
           { dp[i][j][temp] = (dp[i][j][temp]+dp[i][j-1][temp^1^(1<<(i-l))])%p;  }
         }
       }
       for(re int j=0; j<=m; j++)
       {
         for(re int temp=0; temp<(1<<k); temp++)
         { dp[i+1][j][temp<<1] = (dp[i][j][temp]+dp[i+1][j][temp<<1])%p;  }
       }
     }
     printf("%d\n",dp[n][m][0]);
     return 0;
   }
}
signed main()
{ return OMA::main(); }
上一篇:树的三种非递归遍历实现


下一篇:Nginx配置动静分离