luogu P6239 奇怪的道路
我看不出来是状压的状压
好吧,其实看到k的范围应该去往状压方面想的。
然后,题目中说“任何一个城市都与恰好偶数条道路相连(0也被认为是偶数)”。
所以,奇偶,两种状态可以用0,1来表示,那就妥妥的状压了。
设 \(dp_{i,j,sta}\) 表示当前已经考虑了i座城市,j条道路,当前状态为sta的方案数。
用0表示奇数,1表示偶数,为了防止转移时出现问题,所以只转移第i个城市的前k个城市,通过异或能够将连边的两个城市由奇变偶,由偶变奇。
则有
\[dp_{i,j,sta}=\sum_{l=i-k}^{i-1}\sum_{sta=0}^{2^{k+1}-1}dp_{i,j-1,sta^{\wedge}1^{\wedge}2^{i-1}}
\]
因为在转移的时候,sta表示的范围在发生变化,所以对于每一个i都要再单独处理一下
\[dp_{i+1,j,sta\times 2}=\sum_{j=0}^{m}\sum_{sta=0}^{2^{k}-1}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(); }