Data structure you've never heard of(列舉+dp)
阿新 • • 發佈:2018-11-07
沒有來源。
題目大意:
給
個長度為
的01串,求不下降序列的個數。
n≤100000,k≤16
解:
這個不是正常的16維偏序。
作為一個從未見過的資料結構,這道題感覺還挺妙的。
首先很容易想到一個dp。狀壓一下表示當前以那個數結尾的不下降序列個數。但是這樣的複雜度過不了,
如何優化這個做法?
要是把剛才那個過程看作兩步:
1.計算這個數結尾的答案
2.把這個答案放進dp陣列
誒,1,2步複雜度差距太大了,我們能不能平衡一下呢?
事實證明是可以的。
我們狀態定義兩維: 表示前八位為 ,後八位是 的子集的方案數。轉移的時候只用在前八位列舉 的子集,算出答案後再列舉包含 的後八位給dp陣列賦值。
居然就解決了!
orz根本想不到好吧。
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
using namespace std;
long long f[256][256],ans;
char s[25];
int n,k,t;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
long long st=1;t=0;
scanf("%s",s+1);
for(int j=1;j<=k;j++)
if(s[j]=='1')
t+=(1<<(k-j));
for(int j=0;j<=255;j++)
if((j&(t>>8))==j)
st=(st+f[j][t&255])%mod;
ans=(ans+st)%mod;
for(int j=0;j<=255;j++)
if(((t&255)&j)==(t&255))
f[t>>8][j]=(f[t>>8][j]+st)%mod;
}
printf("%lld",ans);
}