方程很好想。转移的话预处理减掉一些废状态。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long n,kk,f[10][100][1024],top,cnt[1024]; bool vis[1024],map[1024][1024]; long long lowbit(long long x) {return (x&(-x));} void pre_build() { for (long long i=0;i<=top;i++) { if (!(i&(i>>1))) vis[i]=true; for (long long x=i;x;x>>=1) if (x&1) cnt[i]++; } for (long long i=0;i<=top;i++) { if (!vis[i]) continue; for (long long j=0;j<=top;j++) { if (!vis[j]) continue; if ((!(i&j)) && (!(i&(j<<1))) && (!(i&(j>>1)))) map[i][j]=1; } } } void dp() { for (long long i=0;i<=top;i++) f[1][cnt[i]][i]=1; for (long long i=2;i<=n;i++) for (long long k=0;k<=top;k++) { if (!vis[k]) continue; for (long long l=0;l<=top;l++) { if ((!vis[l]) || (!map[l][k])) continue; for (long long j=cnt[k];j<=kk;j++) f[i][j][k]+=f[i-1][j-cnt[k]][l]; } } long long ans=0; for (long long i=0;i<=top;i++) ans+=f[n][kk][i]; printf("%lld\n",ans); } int main() { scanf("%lld%lld",&n,&kk);top=(1<<n)-1; pre_build(); dp(); return 0; }