ARC058 E Iroha and Haiku

开始想了一个七维dp,发现会算重

然后就去看题解了(真颓,没希望了)

显然直接做没啥希望,考虑最基本的容斥

用10^n-不包含(X,Y,Z)的方案数

考虑一个神奇的状压1用001表示,2用010表示,3用100表示。即i用(1<<(i-1))表示

在这里加法操作也有其他的定义

比如:我们"2+3”表示为10100,"3+4"表示为1001000

显然的一点考虑c=a+b+c,那么c所对应的状态一定被a+b+c所对应的状态所包含

同样的,如果c被一个集合S包含,那么S所对应的状态一定可以构成c

比如5+6肯定被2+3+6包含

所以我们用dp[i][j]表示考虑了i个数,当前状态构成的集合状态为j的方案数

转移的话枚举一下当前i选了哪个

如果构成的集合包含了X+Y+Z那么我们就不从dp[i-1][j]转移给它,否则加上去

注意我们发现这里的j最多只有17位是有用的,所以复杂度为n*10*2^17

代码如下:

#include<bits/stdc++.h>
#define Mod 1000000007
using namespace std;
int n,x,y,z,dp[45][1<<18];
int main(){
    scanf("%d%d%d%d",&n,&x,&y,&z);
    int unuse=(1<<(z-1))|(1<<(z+y-1))|(1<<(x+y+z-1));
    dp[0][0]=1;
    int tmp1=(1<<(x+y+z))-1;
    for (int i=1;i<=n;i++){
        for (int j=0;j<=tmp1;j++){
            for (int k=1;k<=10;k++){
                int S=(j<<k)|(1<<(k-1));
                S=S&tmp1;
                if ((S&unuse)!=unuse)
                    dp[i][S]=1ll*(dp[i][S]+dp[i-1][j])%Mod;
            }
        }
    }
    int ans=1;
    for (int i=1;i<=n;i++) ans=1ll*ans*10%Mod;
    for (int i=0;i<=tmp1;i++){
        if ((i&unuse)==unuse) continue;
        ans=ans-dp[n][i];
        if (ans<0) ans+=Mod;
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-08-16 20:23  longint  阅读(194)  评论(0编辑  收藏  举报