题意:
叒是那个老船儿长写的题意:
分析:
显然,每个字母最多出现2次。
如果出现3次,中间那次就可以省掉。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define SF scanf
#define PF printf
#define MOD 998244353
#define MAXM 43046721+100
#define MAXN 20
using namespace std;
int dp[MAXM];
char s[MAXN];
int ind[MAXN],pw[MAXN],otd[MAXN];
int pos(int mask,int x){
return (mask/pw[x])%3;
}
int main(){
int n;
SF("%d",&n);
for(int i=1;i<=n;i++){
SF("%s",s);
int u=s[0]-'a';
int v=s[1]-'a';
ind[v]|=(1<<u);
otd[u]=1;
}
pw[0]=1;
for(int i=1;i<=16;i++)
pw[i]=pw[i-1]*3;
dp[0]=1;
for(int i=0;;i++){
for(int j=pw[16]-1;j>=0;j--)
if(dp[j]){
int now=0;
for(int k=0;k<16;k++)
now|=((pos(j,k)!=0)<<k);
bool flag=1;
for(int k=0;k<16&&flag;k++)
if(ind[k]!=0&&pos(j,k)!=2)
flag=0;
if(flag){
PF("%d %d",i,dp[j]);
return 0;
}
for(int nxt=0;nxt<16;nxt++)
if((otd[nxt]||ind[nxt])&&(pos(j,nxt)==0||(pos(j,nxt)==1&&(now&ind[nxt])==ind[nxt]))){
int now1=j;
if(pos(j,nxt)==0&&(now&ind[nxt])==ind[nxt])
now1+=pw[nxt]*2;
else
now1+=pw[nxt];
(dp[now1]+=dp[j])%=MOD;
}
}
}
}