题意翻译
给你一个长度为n(1<=n<=24)的正整数序列S,再有k(0<=k<=2)个正整数。
求有多少种S的排列方式使得其前缀和不会成为那k个数里的任意一个。 答案对1e9+7取模。
题解:
n<=24,考虑状压DP
设dp[S]表示当前已选的集合为S,sum[S]为当前集合的数的和
sum很好得到,^
dp[S]可以由得到,而x可以通过枚举S中的1,然后异或即可得到
AC代码:
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define LL long long
#define endl '\n'
const int MAXN = 1<<24;
const int MAXM = 1e6+50;
const int MOD = 1e9+7;
const double PI = acos(-1);
inline char getc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getc(); }
while(isdigit(ch)) x=x*10+ch-48,ch=getc();
return x*f;
}
int sum[MAXN],dp[MAXN],a[30],lim[5],n,k;
inline int lowbit(int x){ return x&-x; }
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
n=read();
for(int i=0;i<n;i++) a[i]=read(),sum[1<<i]=a[i];
k=read();
for(int i=0;i<k;i++) lim[i]=read();
for(int i=0;i<n;i++)
if(a[i]!=lim[0] && a[i]!=lim[1])
dp[1<<i]=1;
for(int i=1;i<(1<<n);i++){
sum[i]=sum[i^lowbit(i)]+sum[lowbit(i)];
if(sum[i]==lim[0] || sum[i]==lim[1]) continue;
for(int j=i;j;j-=lowbit(j))
dp[i]=(dp[i]+dp[i^lowbit(j)])%MOD;
}
cout<<dp[(1<<n)-1]<<endl;
return 0;
}
来源:CSDN
作者:Nightmare丶
链接:https://blog.csdn.net/qq_43544481/article/details/104446295