#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] \times f[a][b][d] \times f[a][c][d] \times 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;
}

原文地址:https://www.cnblogs.com/xjqxjq/p/12328949.html

时间: 2024-10-14 08:05:46

#3164. 「CEOI2019」立方填词的相关文章

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

「随笔」基于当下的思考

马德,说好的技术blog,变成日记本了... 下午的时候莫名其妙的感到很颓废,因为自己的不够强大感到忧虑和危机感十足.现在每每行走在技术的道路上,常觉得如履薄冰,如芒在背. 上大学之前和现在的心态其实差别挺大的,视野的开阔远远不止局限于自己的脚下.不过,这里的「上大学之前」只是一个时间描述词,并不觉得大学是最适合学习的地方,我很失望. 世界上的人无论性别,区域,宗教,兴趣爱好,总可以在互联网上找到志趣相同的人,总是可以不断打破自己的常识与惯性思维.总是有在相同领域比自己更强的人,挺好的. 关于知

「Unity」与iOS、Android平台的整合:3、导出的Android-Studio工程

本文属于「Unity与iOS.Android平台的整合」系列文章之一,转载请注明出处. Unity默认导出的是Android-Eclipse工程,毕竟Eclipse for Android开发在近一两年才开始没落,用户量还是非常巨大的. 个人认为AndroidStudio非常好用,能轻易解决很多Eclipse解决不了或者很难解决的问题. 所以我将Unity导出的Andoid工程分为Eclipse和AndroidStudio两部分. 不过我之后的相关内容都会使用AndroidStudio,希望依然

大数据和「数据挖掘」是何关系?---来自知乎

知乎用户,互联网 244 人赞同 在我读数据挖掘方向研究生的时候:如果要描述数据量非常大,我们用Massive Data(海量数据)如果要描述数据非常多样,我们用Heterogeneous Data(异构数据)如果要描述数据既多样,又量大,我们用Massive Heterogeneous Data(海量异构数据)--如果要申请基金忽悠一笔钱,我们用Big Data(大数据) 编辑于 2014-02-2817 条评论感谢 收藏没有帮助举报作者保留权利 刘知远,NLPer 4 人赞同 我觉得 大数据

开放的智力8:实用「成功学」

可实现的「成功学」 现在我想为这里的年轻人介绍一种可实现的「成功学」.希望这个我自创的理论,可以改变很多人的一生. 当我们评价一个事情值不值得去做.应该花多少精力去做的时候,应该抛弃单一的视角,而是分两个不同的维度来看,一是该事件将给我带来的收益大小(认知.情感.物质.身体方面的收益皆可计入),即「收益值」:二是该收益随时间衰减的速度,我称为「收益半衰期」,半衰期长的事件,对我们的影响会持续得较久较长. 这两个维度正交以后就形成了一个四象限图.我们生活.学习和工作中的所有事情都可以放进这个图里面

Linux 小知识翻译 - 「syslog」

这次聊聊「syslog」. 上次聊了「日志」(lgo).这次说起syslog,一看到log(日志)就明白是怎么回事了.syslog是获取系统日志的工具. 很多UINIX系的OS都采用了这个程序,它承担了「获取系统全部的日志」这个维持系统正常运行的重要任务. syslog的本体是「syslogd」这个daemon(一般翻译成守护进程),常驻内存中获取日志. syslog的特点是可以通过配置文件「/etc/syslog.conf」,对「哪种应用程序?哪种重要度的信息?记录在哪个文件中?」等进行细致的

Linux 小知识翻译 - 「日志」(log)

这次聊聊「日志」. 「日志」主要指系统或者软件留下的「记录」.出自表示「航海日志」的「logbook」. 经常听说「出现问题的时候,或者程序没有安装自己预期的来运行的时候,请看看日志!」. 确实,记录了系统和软件详细运行情况的「日志」是信息的宝库,通过日志来解决问题的事例也非常多. 但事实上,「无论如何也不会看日志」的用户也有很多.理由很简单,日志的信息量非常大,全部用眼睛来看的话是非常吃力的. 而且,英语写的日志也会让英文不好的人敬而远之. 虽说「要养成用眼睛来看日志的习惯」,但实行起来却非常

Linux 小知识翻译 - 「补丁」(patch)

这次,聊聊补丁. 当有bug或者安全漏洞的时候,就会发布补丁.打上补丁之后,就能解决相应的bug或者安全漏洞. 那么,「补丁」到底是什么呢? 「补丁」只有少量的代码,一般都是对程序的一部分进行更新或者追加,包括bug修正,安全漏洞修正,功能追加或者变更等等.当然,只有「补丁」是无法运行的. 即,只有将「补丁」附加到原来的程序中,更新原来的程序后,才能运行. 「补丁(patch)」本来是指「打补丁用的小布头」.「patch」正是为了补足现有的程序,堵住程序漏洞的「布头」. 打「补丁」的时候需要用到

Linux 小知识翻译 - 「Linux」怎么读?

主要讨论日语中的读法,所以没有完全按照原文来翻译. 「linux」的读法有很多(这里指在日语中),代表性的读法有以下几种: A). 李纳苦思 B). 李奴苦思 C). 纳依纳苦思 A和B相同的是将 linux开头的「li」发音成「李」.这也是linux之父Linus Torvalds的名字的日语假名(「リーナス?トーバルズ」)的由来. linux中「nu」的发音是怎么样的呢?Linux Online的网页上有说明,而且视频中还有 Linus Torvalds 的发音. http://www.li