题解:
这是一道卡常状压DP题。
f[i]表示当前状态的方案数,dis[i]表示当前状态的步数。那么我们会发现复杂度比较大,所以要稍微卡一下常数,用一下位运算然后mod拿来减就好了(开了O2才过了)。
代码如下:
#include<cstdio>
#include<string>
using namespace std;
const int maxn=16777218,tt=1000000007;
int n,m,b[4],f[maxn],dis[maxn];
int main(){
b[1]=b[2]=-1;
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%d",&dis[1<<i]);
scanf("%d",&m);
for (int i=1;i<=m;i++) scanf("%d",&b[i]);
f[0]=1;
for (int i=1;i<(1<<n);i++) {
int j=i&(-i),k=i; dis[i]=dis[i^j]+dis[j];
if (dis[i]==b[1]||dis[i]==b[2]) continue;
while (k) {
j=k&(-k);
f[i]+=f[i^j];
if (f[i]>=tt) f[i]-=tt;
k=k^j;
}
}
printf("%d\n",f[(1<<n)-1]);
return 0;
}