[期望DP] UNR #1 合唱队形

来源:互联网 发布:win32编程还有用吗 编辑:程序博客网 时间:2024/06/05 09:50

合唱队形


不是很懂期望那一套理论 考试时弃疗了
只打了60部分分 待填坑

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>using namespace std;typedef long long ll;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc(),b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline int read(char *s){char c=nc(); int len=0;for (;!(c>='a' && c<='z');c=nc());for (;c>='a' && c<='z';s[++len]=c,c=nc()); s[++len]=0; return len-1;}const ll P=998244353;const int N=35;int inv[N*N];inline void Pre(){inv[1]=1;for (int i=2;i<N*N;i++)inv[i]=(P-P/i)*inv[P%i]%P;}int n,m;char Str[N];int idx[N][26],all;ll ft[N];ll f[1<<16];inline bool check(int x){for (int i=1;i<=n-m+1;i++){int flag=0;for (int j=1;j<=m && !flag;j++)if (!(x>>(idx[i+j-1][Str[j]-'a']-1)&1))flag=1;if (!flag) return 1;}return 0;}inline ll dp(int now){if (f[now]!=-1) return f[now];if (check(now)) return f[now]=0;int cnt=0;for (int i=1;i<=all;i++)if (now>>(i-1)&1)cnt++;ll ret=(ll)all*inv[all-cnt]%P;for (int i=1;i<=all;i++)if (!(now>>(i-1)&1)){ret+=(ll)inv[all-cnt]*dp(now|(1<<(i-1)))%P;ret%=P;}return f[now]=ret;}int main(){char str[N]; int T,len;freopen("t.in","r",stdin);freopen("t.out","w",stdout);Pre();read(T);while (T--){read(n); read(m);all=0;for (int i=1;i<=n;i++){len=read(str);for (int j=1;j<=len;j++)idx[i][str[j]-'a']=++all;}read(Str);if (n==m){ft[n]=0;for (int i=n-1;~i;i--)ft[i]=(ll)all*inv[n-i]+ft[i+1],ft[i]%=P;printf("%lld\n",ft[0]);}else{memset(f,-1,sizeof(f));printf("%lld\n",dp(0));}}return 0;}

0 0
原创粉丝点击