Typical DP Contest Q - 連結

問題

0, 1からなるn個の文字列wiが与えられる。
wiを並べて書いた文字列で、長さがLであるものはいくつあるか。
出来る文字列が同じならば、wiの並べ方は区別しないものとする。

制約条件

答えはmod 10^9 + 7で求める
n≦510

wi ≦8

L≦100

方針

dp[長さ][最後の7文字][区切りになれる場所] := 場合の数
を1文字ずつ更新するようなDP.


区切りになれる場所の遷移は、
前に区切れる場所で区切った後、残りが単語になっていれば、
今の長さの最後でも区切れる。

ソースコード

const int mod = inf + 7;
int n, l;
int dp[110][1 << 7][1 << 8];
bool word[10][1 << 8];

int main(){
	
	cin >> n >> l;
	rep(i, n){
		int bit = 0;
		string s;
		cin >> s;
		rep(j, s.size()) if(s[j] == '1') bit |= 1 << j;
		word[s.size()][bit] = 1;
	}
	
	dp[0][0][1 << 7] = 1;
	rep(i, l) rep(j, 1 << 7) rep(k, 1 << 8) rep(d, 2){
		
		int nj = j | d << 7;
		int nk = k >> 1;
		rep(m, 8) if(k & 1 << m) if(word[8 - m][nj >> m]) nk |= 1 << 7;
		
		(dp[i + 1][nj >> 1][nk] += dp[i][j][k]) %= mod;
	}
	ll ans = 0;
	rep(i, 1 << 7) rep(j, 1 << 8) if(j & 1 << 7) ans += dp[l][i][j];
	cout << ans % mod << endl;
	
	return 0;
}