BZOJ4861【BJOI2017】魔法咒语题解(AC自动机+DP+矩阵乘法)

【统计】NOIP2016普及组[魔法阵]题解 NOIP2016T4题解。 阅读详情

题目:BZOJ4861.
题目大意:给定 n n n个串 S i S_i Si​和 m m m个串 T i T_i Ti​,现在要用这 S i S_i Si​个串(可重复使用)拼成一个长度为 l l l的串使得拼成的串所有 T i T_i Ti​均未出现,求方案数.注意只要组成方式不同就算不同的方案.
1 ≤ n , m ≤ 50 , 1 ≤ ∑ ∣ S i ∣ , ∑ ∣ T i ∣ ≤ 100 , 1 ≤ l ≤ 1 0 8 1\leq n,m\leq 50,1\leq \sum |S_i|,\sum |T_i|\leq 100,1\leq l\leq 10^8 1≤n,m≤50,1≤∑∣Si​∣,∑∣Ti​∣≤100,1≤l≤108.
数据分成两档,第一档满足 1 ≤ l ≤ 100 1\leq l\leq 100 1≤l≤100,第二档满足 1 ≤ ∣ S i ∣ ≤ 2 1\leq |S_i|\leq 2 1≤∣Si​∣≤2.

一题正解分两段是真的恶心,强行二合一啊…

首先,看到这种套路题肯定先把所有 T i T_i Ti​放进Trie里建AC自动机.

然后考虑一个DP,设 f [ i ] [ j ] f[i][j] f[i][j]表示构造一个长度为 i i i的串,在AC自动机中运行到点 j j j,且不能有任何一个 T i T_i Ti​出现的方案数.

现在我们考虑转移,显然可以枚举每一个串 S k S_k Sk​,若在AC自动机上从状态 j j j开始运行串 S k S_k Sk​到达点 t t t,则 f [ i ] [ j ] f[i][j] f[i][j]可以转移到 f [ i + ∣ S k ∣ ] [ t ] f[i+|S_k|][t] f[i+∣Sk​∣][t].

也就是说:
f [ i ] [ j ] → f [ i + ∣ S k ∣ ] [ t = j → S k ] f[i][j]\rightarrow f[i+|S_k|][t=j\rightarrow S_k] f[i][j]→f[i+∣Sk​∣][t=j→Sk​]

我们先处理出所有不能走到的点(每个 T i T_i Ti​代表的状态在fail树上的整棵子树),在运行时若走到了这么一个点就直接把贡献设为 0 0 0就好了.

发现这个算法的时间复杂度为 O ( l ∑ ∣ T i ∣ ∑ ∣ S i ∣ ) O(l\sum |T_i|\sum |S_i|) O(l∑∣Ti​∣∑∣Si​∣),可以通过第一档数据.

那么第二档数据呢?我们发现这个时候 l l l很大,但是 S i S_i Si​的长度均小于等于 2 2 2,这不是明摆着矩乘么…

但是若 S i S_i Si​的长度为 1 1 1还好做, S i S_i Si​的长度为 2 2 2怎么做?

其实很简单,原来我们的状态矩阵只记录了当前串长为 i i i时的信息,现在只需要多记录串长为 i − 1 i-1 i−1时的信息就好了.

时间复杂度 O ( ( ∑ ∣ T i ∣ ) 3 log ⁡ l ) O((\sum |T_i|)^3\log l) O((∑∣Ti​∣)3logl),可以通过第二档数据.

代码如下:

#include<bits/stdc++.h>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=50,M=100,C=26,mod=1000000007;

int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
int sub(int a,int b){return a-b<0?a-b+mod:a-b;}
int mul(int a,int b){return (LL)a*b%mod;}
void sadd(int &a,int b=1){a=add(a,b);}
void ssub(int &a,int b=1){a=sub(a,b);}
void smul(int &a,int b){a=mul(a,b);}

int n,m,sk,len[N+9];
char s[N+9][M+9],t[M+9];
struct Trie{
  int s[C],fail,cnt;
}tr[M+9];
int cn;

void Build(){cn=1;}

int Insert(char *s,int n){
  int k=1;
  for (int i=1;i<=n;++i)
    if (tr[k].s[s[i]-'a']) k=tr[k].s[s[i]-'a'];
    else tr[k].s[s[i]-'a']=++cn,k=cn;
  ++tr[k].cnt;
  return k;
}

queue<int>q;

void Bfs_fail(){
  tr[1].fail=1;
  for (int i=0;i<C;++i)
    if (tr[1].s[i]) tr[tr[1].s[i]].fail=1,q.push(tr[1].s[i]);
    else tr[1].s[i]=1;
  while (!q.empty()){
  	int t=q.front();q.pop();
  	tr[t].cnt+=tr[tr[t].fail].cnt;
  	for (int i=0;i<C;++i)
  	  if (tr[t].s[i]) tr[tr[t].s[i]].fail=tr[tr[t].fail].s[i],q.push(tr[t].s[i]);
  	  else tr[t].s[i]=tr[tr[t].fail].s[i];
  }
}

int Judge(int st,char *s,int n){
  if (tr[st].cnt) return 0;
  int k=st;
  for (int i=1;i<=n;++i){
    k=tr[k].s[s[i]-'a'];
    if (tr[k].cnt) return 0;
  }
  return k;
}

int dp1[M+9][M+9],ans;
struct matrix{
  
  int n,m,v[M*2+9][M*2+9];
  
  matrix operator * (const matrix &p)const{
  	matrix res=matrix();
  	res.n=n;res.m=p.m;
  	for (int i=1;i<=n;++i)
  	  for (int j=1;j<=m;++j)
  	    for (int k=1;k<=p.m;++k)
  	      sadd(res.v[i][k],mul(v[i][j],p.v[j][k]));
  	return res;
  }
  
}dp2,go;

void Build_dp2(){
  dp2.n=1;dp2.m=cn<<1;
  dp2.v[1][cn+1]=1;
  for (int i=1;i<=n;++i)
    if (len[i]==1){
      int td=Judge(1,s[i],1);
      if (!td) continue;
      sadd(dp2.v[1][td]);
    }
}

void Build_go(){
  go.n=go.m=cn<<1;
  for (int i=1;i<=n;++i)
    if (len[i]==1){
	  for (int j=1;j<=cn;++j){
        int td=Judge(j,s[i],1);
        if (td) sadd(go.v[j][td]);
      }
    }else{
      for (int j=1;j<=cn;++j){
      	int td=Judge(j,s[i],2);
      	if (td) sadd(go.v[j+cn][td]);
      }
    }
  for (int i=1;i<=cn;++i) go.v[i][i+cn]=1;
}

matrix E(int n){
  matrix res=matrix();
  res.n=res.m=n;
  for (int i=1;i<=n;++i) res.v[i][i]=1;
  return res;
}

matrix Power(matrix a,int k){
  matrix res=E(a.n);
  for (;k;k>>=1,a=a*a)
    if (k&1) res=res*a;
  return res;
}

Abigail into(){
  scanf("%d%d%d",&n,&m,&sk);
  for (int i=1;i<=n;++i){
  	scanf("%s",s[i]+1);
    len[i]=strlen(s[i]+1);
  }
  Build();
  for (int i=1;i<=m;++i){
  	scanf("%s",t+1);
  	Insert(t,strlen(t+1)); 
  }
}

Abigail work1(){
  Bfs_fail();
  dp1[0][1]=1;
  for (int i=0;i<sk;++i)
    for (int j=1;j<=cn;++j){
      if (!dp1[i][j]) continue;
	  for (int k=1;k<=n;++k){
	  	if (i+len[k]>sk) continue;
      	int td=Judge(j,s[k],len[k]);
      	if (!td) continue;
      	sadd(dp1[i+len[k]][td],dp1[i][j]);
      }
    }
  for (int i=1;i<=cn;++i) sadd(ans,dp1[sk][i]);
}

Abigail work2(){
  Bfs_fail();
  Build_dp2();
  Build_go();
  dp2=dp2*Power(go,sk-1);
  for (int i=1;i<=cn;++i) sadd(ans,dp2.v[1][i]);
}

Abigail outo(){
  printf("%d\n",ans);
}

int main(){
  into();
  if (sk<=M) work1();
  else work2();
  outo();
  return 0;
}
Picture of ssh key 立即下载

相关推荐

政府科技管理者在推动区域科技成果转化过程中,如何系统性地识别和分析创新资源的配置瓶颈?.docx

政府科技管理者在推动区域科技成果转化过程中,如何系统性地识别和分析创新资源的配置瓶颈?

[BJOI2017]魔法咒语(AC自动机+DP+矩阵快速幂)

AC自动机上跑dp蛮套路的

464

政府科技管理者如何提升区域科技成果转化项目的评价与筛选效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

【BZOJ】4861: [Beijing2017]魔法咒语-AC自动机+DP+矩乘

传送门:bzoj4861 题解 首先把忌讳词建成AC自动机,所有串的endendend结点和可以通过跳failfailfail链到一个endendend结点的点都不能走到(getfailgetfailgetfail时预处理即可)。 当L≤100L\leq 100L≤100时,考虑在AC自动机上DP: DP算是比较套路的了。 设f[i][j]f[i][j]f[i][j]表示已经选择了iii个字符,...

远行客 672

高校技术转移办公室人员在成果转化过程中如何快速提升技术推介效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

两相交错并联Boost电路仿真模型(Simulink仿真实现)

内容概要:本文档系统性地介绍了基于Simulink平台的两相交错并联Boost电路仿真模型,属于电力电子变换器建模与仿真研究的重要组成部分。该模型采用交错并联结构,有效提升了系统效率、降低了输出电流纹波,并具备优良的动态响应与系统稳定性。文档不仅聚焦于该特定拓扑的开环与闭环控制实现,还整合了丰富的配套资源,涵盖多种主流DC-DC变换器(如Buck、Boost、LLC、CLLC)、功率因数校正(PFC)电路、PWM整流器、双向充放电系统以及新能源应用场景(如V2G、微电网)等领域的仿真模型。资源体系强调软开关技术、多相交错控制、系统级建模与参数优化设计,所有内容均提供可运行的Simulink仿真文件,部分包含详细的设计报告、计算书及参考文献,具有较强的工程实践与科研复现价值。; 适合人群:电气工程、自动化、电力电子与电力传动等相关专业的硕士博士研究生、高校科研人员,以及从事新能源发电、电动汽车、电源系统设计等领域的工程技术人员。; 使用场景及目标:①支撑高校电力电子与电力系统方向的科研项目,用于新型拓扑结构的建模与先进控制算法的验证;②服务于本科生与研究生的毕业设计、课程设计及高水平学术论文的仿真复现;③为企业在电源产品研发、新能源系统集成等环节提供成熟的仿真方案参考,缩短研发周期,降低试错成本。; 阅读建议:建议使用者首先访问文档末尾提供的完整资源目录链接,按需下载对应仿真模型;在实践过程中,应重点关注模型的参数配置、控制策略实现细节与仿真工况设置,结合配套的说明文档深入理解其工作原理与设计思路,推荐在MATLAB/Simulink环境中动手调试与二次开发,以充分掌握电力电子系统的核心技术。

模拟题【枚举计数】咒语

咒语 【题目描述】 亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路。正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条。 亮亮拿起纸条的一端,只见上面写着打开机关的方法:“打开机关需要念动符咒,咒语是一串长为LLL 的由000和111组成的字符串。在这张长纸条上列了nnn个长为LLL的字符串,正确的咒语即是在纷繁的 2L2^L2L种字符串中,与这些纸条上的字符串相异度之和最小,并且在满足这一条件下,000的个数最多的字符串。两个字符串的相异度定义为对应位置不相等的字符对的个数

ZYzyZzzz的博客 296

Python对接海康威视机器视觉工业相机

工业相机只允许单条连接,也就是说MVS如果连接了相机,python代码就无法获取数据,此时必须。相机工具类(读者直接复制)HKCamera_class.py。博主这里出现了一个警告:获取不到相机参数。四、使用Pycharm打开Python代码示例文件夹。三、找到MVS示例代码(代码在MVS的安装位置)二、解压并安装MVS客户端。一、下载MVS客户端。安装一下opencv。

Good Luck 2万+

NOIP 2016 PJ T4 魔法阵

     P2119 魔法阵   题目描述   六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量。 大魔法师有m个魔法物品,编号分别为1,2,...,m。每个物品具有一个魔法值,我们用Xi表示编号为i的物品的魔法值。每个魔法值Xi是不超过n的正整数,可能有多个物品的魔法值相同。 大魔法师认为,当且仅当四个编号为a,b,c,d的魔法物品满足xa&lt;xb&l...

Ark 2595

Comsol 管道导波裂纹检测:从建模到求解的完整流程解析

本文详细解析了使用Comsol Multiphysics进行管道导波裂纹检测的完整仿真流程。从几何建模、材料定义、物理场设置到网格划分与求解后处理,系统阐述了如何构建高保真虚拟模型以模拟导波与裂纹的相互作用。重点分享了激励信号设置、频散效应处理及参数化扫描等实战技巧,旨在帮助工程师与研究人员高效优化无损检测方案,降低实验成本。

weixin_29207439的博客 74

光电振荡器(OEO):从原理到应用,解锁高频微波信号新纪元

本文深入解析了光电振荡器(OEO)的核心原理与前沿应用。OEO通过巧妙的光-电-光转换机制,利用光学谐振腔产生高频、高纯度、低相位噪声的微波信号,有效突破了传统电子电路的频率瓶颈。文章详细拆解了其工作流程,并探讨了在雷达系统、高速光通信及精密测量等领域的硬核应用价值。

weixin_29231027的博客 365

bzoj4861 / P3715 [BJOI2017]魔法咒语

P3715 [BJOI2017]魔法咒语 AC自动机+dp+矩阵乘法 常规思路是按基本串建立AC自动机 然鹅这题是按禁忌串建立AC自动机 对后缀是禁忌的点以及它的失配点做上标记$(a[i].ed)$,到时候不访问。 基本串转化为自动机上的边:设$p[j][i]$表示第$j$个节点加上第$i$个串会到的节点编号 在建好AC自动机后可以直接处理。 现在分类讨论(对,两份代码) ...

dingqiongliang0363的博客 254

《遥感大模型生产级实战:从数据到决策的端到端AI工程》系列第一部分:AI遥感工程师的基础设施与工具链-文章 4:传统遥感分析与机器学习基线

本章将系统性地介绍经典遥感分析工作流,从数据预处理到多维度特征工程,再到如何利用经典的机器学习模型(如随机森林、支持向量机)进行监督与非监督学习。我们将通过一个完整的“智慧农业作物分类”项目实战,展示如何利用我们之前构建的数据湖和工具链,从原始数据到最终的分析结果,构建一个性能可靠、可解释性强的基线系统。更重要的是,我们将深入剖析这种传统方法的局限性,从而为后续章节引入遥感大模型的必要性提供强有力的论证。

panshengwu的博客 705

【BZOJ4861】[Beijing2017]魔法咒语 矩阵乘法+AC自动机+DP

【BZOJ4861】[Beijing2017]魔法咒语 题意:别看BZ的题面了,去看LOJ的题面吧~ 题解:显然,数据范围明显的分成了两部分:一个是L很小,每个基本词汇长度未知;一个是L很大,每个基本词汇的长度是1或2。看来只能写两份代码了。 对于L很小的,我们先将禁忌串建成一个AC自动机,然后预处理出to[i][j]表示AC自动机中的第i个节点在加入基本词汇j后会到达的节点。然后...

aodanchui1057的博客 174

基于Simulink的光伏+储能家庭能源管理系统仿真

本文通过Simulink建模,分析了家庭光伏+储能系统的优化调度问题。针对光伏发电与用电高峰不匹配导致电费节省有限的问题,构建了包含5kW光伏、10kWh电池和6kW负荷的完整模型,设计了无控、规则控制和24小时经济优化三种策略。仿真结果显示,经济优化策略可使日电费降低32%,光伏自用率从45%提升至89%,尤其在晚高峰时段能显著减少高价购电。文章详细介绍了物理层建模、分时电价实现和控制策略设计方法,并探讨了天气预测、V2H等高级扩展功能,为家庭能源智能管理提供了实用解决方案。

xiaoheshang_123的博客 188

【React】1、React入门与概览(JSX语法)

React入门 文章目录React入门一、React全家桶1. React是什么?2. 谁开发的?3. 为什么要学?4. React的特点5. 学习React之前要掌握的JavaScript基础知识二、React 概览组件JSXVirtual DOM关于虚拟DOM:Data Flow三、React基本使用相关js库四、React JSXJSX 语法规则五、模块与组件、模块化与组件化的理解5.1 模块5.2 组件5.4 模块化5.5 组件化 一、React全家桶 React基础 React-Router(R

Coding and studying 1379

【BZOJ4861】【BJOI2017】—魔法咒语(AC自动机+矩阵快速幂优化dp)

传送门 当l≤100l\le 100l≤100时 显然的自动机上dpdpdp就完了 当l≤1e8l\le1e8l≤1e8时直接dpdpdp显然是不行的 但是发现基本串长度不大于二 考虑矩乘优化 a[i][j]a[i][j]a[i][j]表示有几个基本串使得在自动机上iii走到jjj 如果所有串长相同就可以直接快速幂了 但是串长有111有222 不同长度不好处理拼起来的情况 设A1A_1A1​表示长...

Stargazer的博客 286

高级数据库--作业及答案

中科大金培权老师的高级数据库课程作业及答案

一杯水果茶!足矣~ 1658

[bzoj4861]魔法咒语

题目描述瞎做显然是AC自动机dp。 小的直接dp大的矩阵乘法。#include<cstdio> #include<algorithm> #include<cstring> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; typedef long long ll; const int maxn=200+10,mo=1000000007

不来也不去的一只失忆蝴蝶 1004

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

[BZOJ4861][BJOI2017]魔法咒语(AC自动机+矩阵优化DP)

4861: [Beijing2017]魔法咒语 Time Limit: 20 SecMemory Limit: 256 MBSubmit: 217Solved: 105[Submit][Status][Discuss] Description Chandra 是一个魔法天才。 从一岁时接受火之教会洗礼之后, Chandra 就显示出对火元素无与伦比的亲和力,轻...

weixin_30871701的博客 148

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

P3619 魔法 题解

旅行传送门:快来点我鸭 题目描述 cjwssb知道是误会之后,跟你道了歉。你为了逗笑他,准备和他一起开始魔法。不过你的时间不多了,但是更惨的是你还需要完成n个魔法任务。假设你当前的时间为T,每个任务需要有一定的限制ti表示只有当你的T严格大于ti时你才能完成这个任务,完成任务并不需要消耗时间。当你完成第i个任务时,你的时间T会加上bi,此时要保证T在任何时刻都大于0,那么请问你是否能完成这n个魔法任务,如果可以,输出+1s,如果不行,输出-1s。 输入格式 第一行:一个整数Z,表示有Z个测试点。 对于每个测

Foxreign的博客 472

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

bzoj4861 [Beijing2017]魔法咒语(AC+矩阵优化dp)

DescriptionChandra 是一个魔法天才。从一岁时接受火之教会洗礼之后,Chandra 就显示出对火元素无与伦比的亲和力,轻而易举地学会种种晦涩难解的法术。这也多亏 Chandra 有着常人难以企及的语言天赋,让她能轻松流利地说出咒语中那些极其拗口的魔法词汇。直到十四岁,开始学习威力强大的禁咒法术时,Chandra 才遇到了障碍。根据火之魔法规则,禁咒的构成单位是 N 个基本词汇。施法时

Coco_T的博客 692

[BZOJ4861][Beijing2017]魔法咒语 AC自动机+动态规划+矩阵快速幂

对忌讳词语构建AC自动机 Fi,jF_{i,j}表示长度为ii,匹配到AC自动机第jj位的合法串方案数 当状态数少的时候用矩阵转移#include <bits/stdc++.h> #define N 5050 const int mod = 1e9+7; using namespace std; typedef long long LL; int len[105],cnt,n,m,l,ans;

HbFS- 1174

【题解】咒语

【题目描述】 亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路。 正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条。 亮亮 拿起纸条的一端,只见上面写着打开机关的方法:“打开机关需要念动符咒,咒 语是一串长为 L 的由 0 和 1 组成的字符串。在这张长纸条上列了 n 个 长为 L 的字符串,正确的咒语即是在纷繁的 2^L 种字符串中,与这些纸条上的 字符串 相异度...

cjx的博客 671
上一篇: LOJ145 DFS序2(dfs序模板)
下一篇: BZOJ3038 上帝造题的七分钟题解(树状数组+并查集)
hezlik
博客等级 码龄9年 111粉丝 241原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值