【BJOI2017】魔法咒语

2024-04-16 13:18
文章标签 魔法 咒语 bjoi2017

本文主要是介绍【BJOI2017】魔法咒语,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

时间限制 : 1000 MS 空间限制 : 131072 KB

问题描述

Chandra 是一个魔法天才。
从一岁时接受火之教会洗礼之后,Chandra 就显示出对火元素无与伦比的亲和力,轻而易举地学会种种晦涩难解的法术。这也多亏 Chandra有着常人难以企及的语言天赋,让她能轻松流利地说出咒语中那些极其拗口的魔法词汇。

直到十四岁,开始学习威力强大的禁咒法术时,Chandra 才遇到了障碍。

根据火之魔法规则,禁咒的构成单位是 N 个基本词汇。施法时只要凝聚精神力,说出一段用这些词语组成的长度恰好等于 L 的语言,就能释放威力超乎想象的火法术。过去的魔法师们总结了几种表达起来最连贯的组合方式,方便施法者以最快语速完成法术。

但具有魔法和语言双重天才的 Chandra不满足于这几种流传下来的禁咒,因为她可以毫无困难地说出普通人几乎不可能表达的禁咒语句。然而,在实际施法时,Chandra 发现有些自创禁咒念出后不但没有预期效果,反而会使自己的精神力迅速枯竭,十分难受。

这个问题令 Chandra 万分不解。她大量阅读典籍,到处走访魔法学者,并且不顾精神折磨一次又一次尝试新咒语,希望找出问题的答案。

很多年过去了,在一次远古遗迹探险中,Chandra意外闯进了火之神艾利克斯的不知名神殿。根据岩土特征分析,神殿应该有上万年的历史,这是极其罕见的。Chandra 小心翼翼地四处探索,沿着魔力流动来到一间密室。她看见密室中央悬浮着一本书籍。在魔法保护下书籍状况完好。精通上古语言的 Chandra 读过此书,终于解开了多年的困惑。

禁咒法术之所以威力强大,是因为咒语借用了火之神艾利克斯的神力。这本书里记载了艾利克斯生平忌讳的 M 个词语,比如情敌的名字、讨厌的植物等等。使用禁咒法术时,如果语言中含有任何忌讳词语,就会触怒神力而失效,施法者也一并遭受惩罚。

例如,若 ”banana” 是唯一的忌讳词语,“an”、”ban”、”analysis” 是基本词汇,禁咒长度须是11,则“bananalysis” 是无效法术,”analysisban”、”anbanbanban”是两个有效法术。注意:一个基本词汇在禁咒法术中可以出现零次、一次或多次;只要组成方式不同就认为是不同的禁咒法术,即使书写形式相同。

谜题破解,Chandra 心情大好。她决定计算一共有多少种有效的禁咒法术。

由于答案可能很大,你只需要输出答案模 1,000,000,007 的结果。

输入格式

第一行,三个正整数 N, M, L。
接下来 N 行,每行一个只含小写英文字母的字符串,表示一个基本词汇。
接下来 M 行,每行一个只含小写英文字母的字符串,表示一个忌讳词语。

输出格式

仅一行,一个整数,表示答案(模 10^9+7)。

样例输入 1

4 2 10
boom
oo
ooh
bang
ob
mo

样例输出 1

14

样例输入 2

3 1 3
a
ab
aba
aaa

样例输出 2

3

样例输入 3

3 1 14
ban
an
analysis
banana

样例输出 3

15

提示

样例解释 1】

有效的禁咒法术共有 14 种:boom/bang/oo,oo/oo/oo/oo/oo,oo/oo/ooh/ooh,

oo/ooh/oo/ooh,oo/ooh/ooh/oo,ooh/oo/oo/ooh,ooh/oo/ooh/oo,

ooh/ooh/boom,ooh/ooh/oo/oo,ooh/ooh/bang,ooh/bang/ooh,

bang/oo/oo/oo,bang/ooh/ooh,bang/bang/oo。

【样例解释 2】

有效的禁咒法术有 a/ab, ab/a, aba 共三种。注意,ab/a 和 aba 算成两种不同的禁咒法术。

【数据规模与约定】

本题一共有 10 个测试点。

下表是每个测试点的数据规模和约定:
这里写图片描述

题解

题目描述有点长,看起来比较吓人,但题意还是比较简单的。
对于前60%的数据,直接对忌讳词语建AC自动机,然后在机子上跑记忆化搜索或递推就可以了。
本题主要难点在后40%,尤其是最后20%的数据上。我们可以把AC自动机看成一张图,在字符串后接上某基本词语就相当于从图上一点走一条路径到达另一点。观察数据的特殊性——基本词语长度为1或2且 L L 很大。如果所有基本词语长度都只有1,那么在图上的转移路径就只会经过一条边,题目问题就转化为了已知图上两点间有一条边,求从起点(AC自动机根节点)出发走L条边后在任意点停下的方案数——经典的矩阵乘法问题!要处理禁忌词汇,只需提前预处理出所有路径的起止点,当终点为某禁忌词汇的末尾时,删去该路径即可。对于基本词语长度为2的情况,我们需要构造虚拟点在原路径的起止点间做中转,相当于起点到终点需走两步(经过两条边),注意最后计算结果时不能包含虚拟点!
为什么前60%的数据不能用后40%的方法?基础词汇太长->虚拟点太多->时空复杂度爆炸!
详见代码……

代码

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef ll arr[205][205];
const ll mod=1e9+7;
ll n,m,l,tot,val[105],fail[105],trie[105][30],G[105][55];
ll N,ans,f[105][105];
arr I,A;
char c[55][105],tab[105];
queue<ll> q;
namespace ACAM
{void Insert(){ll p=0,len=strlen(tab+1);for(ll i=1;i<=len;i++){ll t=tab[i]-'a';if(!trie[p][t]) trie[p][t]=++tot;p=trie[p][t];}val[p]++;}void Getfail(){for(ll i=0;i<26;i++)if(trie[0][i]) q.push(trie[0][i]);while(!q.empty()){ll x=q.front();q.pop();for(ll i=0;i<26;i++){ll son=trie[x][i];if(!son){trie[x][i]=trie[fail[x]][i];continue;}q.push(son);ll y=fail[x];while(y&&!trie[y][i]) y=fail[y];fail[son]=trie[y][i],val[son]|=val[fail[son]];}}}ll Goto(ll p,ll x){ll len=strlen(c[x]+1);for(ll i=1;i<=len;i++)if(!val[trie[p][c[x][i]-'a']]) p=trie[p][c[x][i]-'a'];else return -1;return p;}ll DFS(ll p,ll step){if(step==l) return 1;if(~f[p][step]) return f[p][step];f[p][step]=0;for(ll i=1;i<=n;i++)if((~G[p][i])&&step+strlen(c[i]+1)<=l)f[p][step]=(f[p][step]+DFS(G[p][i],step+strlen(c[i]+1)))%mod;return f[p][step];}
}
namespace matrix
{void mul(arr y,arr x){arr z;memset(z,0,sizeof(z));for(ll i=0;i<=N;i++)for(ll j=0;j<=N;j++)for(ll k=0;k<=N;k++)z[i][j]=(z[i][j]+y[i][k]*x[k][j]%mod)%mod;memcpy(y,z,sizeof(z));}void ksm(ll b){for(ll i=0;i<=N;i++) I[i][i]=1;while(b){if(b&1) mul(I,A);b>>=1;mul(A,A);}}
}
int main()
{scanf("%lld%lld%lld",&n,&m,&l);for(ll i=1;i<=n;i++) scanf("%s",c[i]+1);for(ll i=1;i<=m;i++) scanf("%s",tab+1),ACAM::Insert();ACAM::Getfail();for(ll i=0;i<=tot;i++)for(ll j=1;j<=n;j++) G[i][j]=ACAM::Goto(i,j);if(l<=100){memset(f,-1,sizeof(f));ACAM::DFS(0,0);printf("%lld\n",f[0][0]);}else{N=2*tot+1;for(ll i=0;i<=tot;A[i][i+tot+1]++,i++)for(ll j=1;j<=n;j++)if(~G[i][j])if(strlen(c[j]+1)==1) A[i][G[i][j]]++;else A[i+tot+1][G[i][j]]++;matrix::ksm(l);for(ll i=0;i<=tot;i++) ans=(ans+I[0][i])%mod;printf("%lld\n",ans);}return 0;
}

这篇关于【BJOI2017】魔法咒语的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908889

相关文章

探索Python的数学魔法:Numpy库的神秘力量

文章目录 探索Python的数学魔法:Numpy库的神秘力量背景:为什么选择Numpy?Numpy是什么?如何安装Numpy?五个简单的库函数使用方法场景应用常见Bug及解决方案总结 探索Python的数学魔法:Numpy库的神秘力量 背景:为什么选择Numpy? 在Python的世界中,数据处理和科学计算是不可或缺的一部分。但原生Python在处理大规模数据时可能会显

玩转Python Turtle库,实现满屏飘字的魔法!

前言     本文将教你如何使用Python的Turtle库,通过简单的编程实现满屏飘字的炫酷效果。无需复杂的编程知识,跟着我们的步骤,你也可以成为编程小达人! 效果展示 开发过程 一、准备工作 首先,确保你的电脑上已经安装了Python环境。然后,你需要安装或更新Turtle库(通常Python安装时自带了Turtle库)。 二、编写代码 接下来,我们将通过编写一个简单的P

重复采样魔法:用更多样本击败单次尝试的最强模型

这篇文章探讨了通过增加生成样本的数量来扩展大型语言模型(LLMs)在推理任务中的表现。 研究发现,重复采样可以显著提高模型的覆盖率,特别是在具有自动验证工具的任务中。研究还发现,覆盖率与样本数量之间的关系可以用指数幂律建模,揭示了推理时间的扩展规律。尽管多数投票和奖励模型在样本数量增加时趋于饱和,但在没有自动验证工具的任务中,识别正确样本仍然是一个重要的研究方向。 总体而言,重复采样提供了一种

07_TensorFlow2图像编解码大揭秘:让图片说‘变’就‘变’,魔法还是科技?

1. 图像的编码和解码 在实际应用中,图像数据源格式多种多样,如:png\jpg\bmp等,而神经网络训练模型所需的图像的数据格式为:图像字节数据或Base64编码数据等。基于此,将png\jpg\bmp等格式的图像转换为字节数据的过程称为图像编码,将字节数据的图像转换为png\jpg\bmp等格式图像的过程称为图像解码。 2. 图像编码 Tensorflow图像编码的过程如下图所示,分

【Jupyter】 Notebook 中的 IPython 魔法:12个必知实用技巧

Jupyter Notebook 作为一个强大的交互式计算环境,结合 IPython 的功能,为数据科学家和程序员提供了丰富的工具。本文将介绍12个在 Jupyter Notebook 中使用 IPython 的实用技巧 1. 清除输出:使用 clear_output() from IPython.display import clear_output# 执行一些操作print("This

【深度学习 激活函数】激活函数:深度学习界的“魔法药剂”

大家好!今天我们来聊聊深度学习中的一个重要角色——激活函数。你是否曾经好奇过,为什么神经网络能像魔法一样识别图片、理解和生成文字?答案就在于这些神奇的激活函数! 激活函数:神经网络的“心跳” 想象一下,神经网络就像一个巨大的生物体,而激活函数就是它的心跳。没有心跳,生物体就无法生存;同样,没有激活函数,神经网络就无法正常工作。 激活函数的“魔法” 激活函数就像是给神经网络施加了魔法,让它们

【C#编程技术总结】魔法包唤醒同一局域网设备

目录 一、原理 Wake-on-LAN (WOL) 的工作原理 典型应用场景 配置要求 注意事项 二、代码 一、原理 魔术包(Magic Packet)是Wake-on-LAN(WOL)技术的一部分,它允许远程唤醒网络设备,如计算机或服务器。这个功能通常用于节能和远程管理,当设备处于待机或休眠状态时,可以通过网络将其唤醒,而无需物理操作。 Wake-on-LAN (WOL

Python中的集合魔法:解锁高效数据处理的秘密

引言 集合是一种不允许重复元素的数据结构,并且其内部元素无序排列。这种特性使得集合在某些场景下表现得极为出色: 去重:快速去除列表或数组中的重复项。交集、并集、差集等运算:用于比较两个或多个集合间的关系,非常适用于权限控制、用户管理等领域。性能优势:相较于列表,集合在查找元素时速度更快,平均时间复杂度为O(1)。 基础语法介绍 创建集合 在Python中创建一个空集合需要使用set()函

AI绘图提示词/咒语/词缀/关键词使用指南(Stable Diffusion Prompt 最强提示词手册)

一、为什么学习AI绘画关键词 在人工智能技术飞速发展的今天,AI绘画已成为艺术领域的一大热点。学习AI绘画关键词,不仅有助于我们掌握这一新兴技术,还能拓宽我们的创作思路,实现艺术与技术的完美融合。以下是学习AI绘画关键词的几个原因: 提升创作效率:AI绘画可以帮助我们快速生成草图、概念图和成品图,大大提高创作效率。拓宽创作领域:掌握AI绘画关键词,可以让我们在数字艺术、游戏设计、动画制作等多个

CSS选择器的魔法:探索:not-child()与:nth-child()

CSS选择器是前端开发中的强大工具,它们允许我们以精确的方式选择和操作网页上的元素。在这篇文章中,我们将深入探讨两个非常有用的CSS选择器::not-child()和:nth-child()。通过这些选择器,我们可以创建动态且具有吸引力的网页布局。 :not-child():排除特定元素 :not-child()选择器允许我们排除特定元素,从而对其他元素应用样式。这在创建复杂的布局时非常有用,