zoukankan      html  css  js  c++  java
  • #3164. 「CEOI2019」立方填词

    题目描述

    题解

    先按照长度分类,因为正反读都可以,所以对于每个长度我们可以把串正反都记录下来并且去重,由于我们只关心首尾的字母是什么,所以我们可以记录 $g[a][b]$ 表示开始为 $a$ ,结尾为 $b$ 的串有多少个。

    然后这是一个正方体,最暴力我们可以考虑枚举每个角是什么,然后统计方案,但事实上我们可以先统计形如下图的方案数,即不管棱的交点放了什么,如果剩下的顶点分别 $b,c,d$ 的话有多少种方案,我们把这个方案数设为 $f[b][c][d]$ 。

    然后我们可以发现形如下图,我们可以把正方体分成 $4$ 个上图图形,即顶点 $A,B,C,D$ ,剩下的顶点如果填上 $a,b,c,d$ 的话,那方案数就是 $f[a][b][c] imes f[a][b][d] imes f[a][c][d] imes f[b][c][d]$ 。

    然后我们需要卡常,比如求 $f$ 的时候让 $b le c le d$ 即可,求方案数的时候让 $a le b le c le d$ 即可,注意求方案数要乘上排列数。

    代码

    #include <bits/stdc++.h>
    #define U unsigned long long
    using namespace std;
    const U B=793999;
    const int P=998244353,N=62;
    char ch[15];map<U,int>mp;
    int n,m,g[15][N][N],f[N][N][N],t[N],s;
    int X(int x){return x>=P?x-P:x;}
    int G(char x){
        if (x>='a' && x<='z') return x-'a';
        if (x>='A' && x<='Z') return x-'A'+26;
        return (x^48)+52;
    }
    int main(){
        cin>>n;
        for (int i=1;i<=n;i++){
            scanf("%s",ch+1);
            m=strlen(ch+1);U v=0;
            for (int j=1;j<=m;j++) v=v*B+ch[j];
            if (!mp.count(v))
                mp[v]=1,g[m][G(ch[1])][G(ch[m])]++;
            v=0;
            for (int j=m;j;j--) v=v*B+ch[j];
            if (!mp.count(v))
                mp[v]=1,g[m][G(ch[m])][G(ch[1])]++;
        }
        for (int x=3;x<=10;x++){
            memset(f,0,sizeof f);
            for (int a=0;a<N;a++)
                for (int b=0;b<N;b++) if (g[x][a][b])
                    for (int c=b;c<N;c++) if (g[x][a][c])
                        for (int d=c;d<N;d++) if (g[x][a][d])
                            f[b][c][d]=X(f[b][c][d]+1ll*g[x][a][b]*g[x][a][c]%P*g[x][a][d]%P);
            int p=24;
            for (int a=0;a<N;a++){
                t[a]++;p/=t[a];
                for (int b=a;b<N;b++){
                    t[b]++;p/=t[b];
                    for (int c=b;c<N;c++) if (f[a][b][c]){
                        t[c]++;p/=t[c];
                        for (int d=c;d<N;d++){
                            t[d]++;p/=t[d];
                            s=X(s+1ll*p*f[a][b][c]%P*f[a][b][d]%P*f[a][c][d]%P*f[b][c][d]%P);
                            p*=t[d];t[d]--;
                        }
                        p*=t[c];t[c]--;
                    }
                    p*=t[b];t[b]--;
                }
                p*=t[a];t[a]--;
            }
        }
        cout<<s<<endl;return 0;
    }
  • 相关阅读:
    关于springMVC的一些常用注解
    关于springMVC的一些xml配置
    关于easyUI的一些js方法
    关于easyUI一些标签的使用
    关于easyUI分页
    P3376 模板网络流
    P1343 地震逃生
    网络流最大流
    python函数知识三 函数名的使用、格式化、递归
    python函数知识二 动态参数、函数的注释、名称空间、函数的嵌套、global,nonlocal
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12328949.html
Copyright © 2011-2022 走看看