bzoj搬题

只讲解题方法,不讲题目题意

代码风格为个人喜好,请体谅

bzoj 1879 状态压缩dp -

设g[i][j]表示匹配到i位该位字符选j的集合
设f[i][j]为匹配打i位,集合位j的方案数
枚举每一位的字符得出g[i][j]
f[i][j]->f[i+1][j&g[i][ch]]
答案即为
sigma{f[len][set(popcount1==k)]}
复杂度为 o(set*n*len)=o(2^15*15*50)
#include<bits/stdc++.h>
using namespace std;
const int mod= (int) 1e6 + 3 , N = 52 ;
int n,k,ans=0;
int g[N][100],f[N][(1<<15)+20],len;
char s[20][N];
int count(int x) {
	int ans=0;for(;x;ans+=(x&1),x>>=1);return ans;
}
void add(int &x,int y) {x+=y;for(;x>=mod;x-=mod);}
main() {
    int t;
    for(scanf("%d",&t);t;t--) {
        memset(g,0,sizeof(g));ans=0;memset(f,0,sizeof(f));
        cin>>n>>k;
        for(int i=0;i<n;i++) scanf("%s",s[i]);len =strlen(s[0]);
        for(int i=0;i<n;i++)
            for(int j=‘a‘;j<=‘z‘;j++)
                for(int l=0;l<len;l++) if(s[i][l]==‘?‘||s[i][l]==j)
                    g[l][j-‘a‘]|=(1<<i);
        f[0][(1<<n)-1]=1;
        for(int i=0;i<len;i++)
            for(int j=0;j<(1<<n);j++) if(f[i][j])
                for(int ch=‘a‘;ch<=‘z‘;ch++)
                    add(f[i+1][g[i][ch-‘a‘]&j],f[i][j]);
        for(int j=0;j<(1<<n);j++) if(count(j)==k) add(ans,f[len][j]);
        cout<<ans<<"\n";
    }
}
时间: 2024-08-01 22:35:08

bzoj搬题的相关文章

BZOJ 刷题记录 PART 4

[BZOJ1143]CTSC的题目...先用floyed传递闭包,然后直接上匈牙利算法. [BZOJ1452]从未写过的二维树状数组.好像很简单.. struct two_bit { int f[305][305]; inline void add(int x,int z,int A) { for (;x<=n;x+=L(x)) for (int y=z;y<=m;y+=L(y)) f[x][y]+=A; } inline int ask(int x,int z) { int ans=0; f

BZOJ 刷题记录 PART 5

拖了好久才写的. [BZOJ2821]接触分块大法.这道题略有点新颖.首先我们先分块,然后统计每块中每个数出现的个数. 下面是联立各个方块,预处理出第I个方块到第J个方块出现正偶数次数的个数. for (i=1;i<=s;i++) { for (j=i;j<=s;j++) { sum[i][j]=sum[i][j-1]; for (k=a[j].l;k<=a[j].r;k++) { temp[data[k]]++; if (!(temp[data[k]]&1)) sum[i][j

【BZOJ做题记录】07.07~?

在NOI一周前重开一个坑 最后更新时间:7.07 11:26 7.06 下午做的几道CQOI题: BZOJ1257: [CQOI2007]余数之和sum:把k mod i写成k-k/i*i然后分段求后面的部分就好了 BZOJ1258: [CQOI2007]三角形tri:在草稿纸上按照位置和边找一下规律就好了 BZOJ1260: [CQOI2007]涂色paint:简单的区间DP BZOJ1303: [CQOI2009]中位数图:小于中位数的改为-1大于的改为1,算一算前缀和然后哈希一下乘一乘就好

BZOJ 刷题记录 PART 1

作者 : Dolphin 原文地址:http://blog.csdn.net/qingdujun/article/details/27109035 一.实体完整性定义 [例1]将Student表中的Sno属性定义为码. CREATE TABLE Student ( Sno CHAR(10) PRIMARY KEY, /*在列定义主码*/ Sname CHAR(20) NOT NULL, Sage SMALLINT ); 或者: CREATE TABLE Student ( Sno CHAR(10

BZOJ 刷题记录 PART 2

[前言]最近感觉状态不错.做题几乎不看题解了.(一群大牛(FZ&WCY)在旁边喷:你刷水题有意思!)但是至少这也是一种进步吧.特别是权限题中有很多思维题. [BZOJ1055]就是一个简单的区间DP.重要代码: for (l=2;l<=L;l++) for (i=1;i<=L-l+1;i++) { j=i+l-1; for (k=0;k<4;k++) for (cut=i;cut<j;cut++) for (p=0;p<4;p++) if (f[i][cut][p])

BZOJ 刷题记录 PART 3

[前言]还是强调要少看题解. [BZOJ1090]简单的区间DP.值得注意的是:在压缩的时候,如果是10个A压缩,那么化成(10)A后有5个字符而不是4个!(我在这里被坑了好长时间!)以下是核心代码: for (len=2;len<=L;len++) for (i=1;i<=L-len+1;i++) { j=i+len-1; for (k=i;k<j;k++) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); for (l=1;l<=len/2;l++

BZOJ 刷题记录 PART 6

[BZOJ2709]水的二分加验证.可是好像被读入萎到了... [BZOJ3229]强大的算法见此.被机房的一堆大神"推荐".于是被坑了...写了一个下午... [BZOJ3631]这道题给我的启发是:要多想想算法. 開始一直在打树链剖分,打到一半忽然在众神犇的提(bi)示(shi)下.发现有O(N)的方法.试想:假设要支持区间改动(加减),最后再查询,能够用什么方法?固然,线段树和树状数组等等都能够,可是最好的显然是类似于前缀和的思想.比方在L~R加上一个数,能够再L处+K.在R+1

BZOJ做题记录[0512~?]

觉得做一道开一篇真不好...好多想找的东西都被刷下去了... 至于?的日期究竟到什么时候...还是看心情...但是估计不会超过七天吧 05.12 当然是用刷水题来开启新的一天>< 感觉啊...这道题怎么做都可以..所以索性不说了 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #define INF 1000000007 6 #defin

cf搬题

rand 题基本上是CD吧,AB不想做,E太难了233~ + 看别人代码 - 自己写的 * 看题解的 315D + 给定两个string a b,以及他们出现的次数c,d 求找到一个最大p,使得整个b串为a的子串. 我们对于b的每一位都找到a串的结束的位置nxt数组,然后如果匹配了,把b串的cnt++,最后统计答案,就是根据nxt的跳跃统计cnt就可以了, 254C + 给定两个串,求改变a串最少的顺序,使得a中的每一个字符出现的次数等同于b出现的次数,并输出字典序最小的方案. - naive的