码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj搬题

时间:2017-08-15 15:12:18      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:c++   字符   return   ==   bit   pop   题目   方法   out   

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

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

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";
    }
}

 

bzoj搬题

标签:c++   字符   return   ==   bit   pop   题目   方法   out   

原文地址:http://www.cnblogs.com/foreverpiano/p/bzoj.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!