【Codeforces 506E】Mr.Kitayuta’s Gift&&【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化
神题……
胡乱讲述一下思维过程……
首先,读懂题.
然后,转化问题为构造一个长度为|T|+n的字符串,使其内含有T这个子序列.
之后,想到一个简单的dp.由于是回文串,我们就增量构造半个回文串,设f(i,j,k)为构造到第i个位置,从前往后匹配到j,从后往前匹配到k,这样O(m*m*n)(没有观察到其转移的性质会再乘个26).
再然后,发现不妙,在最后讨论奇偶.
(我的思路到此为止……)
接着,观察其转移的实质,发现其实dp的过程就是在一个有限状态自动机上行走,而有限状态自动机上的状态就是目前剩下的T,所以我们只不过是要求出从起点到某些点的路径条数(事先声明步数).
到了现在,我们的目的只不过是统计到不同终点的路径条数,那么:第一步,点集相同的路径合并起来,点集不同,一定不同;第二步,对于点集相同的路径们,他们走自环的总数一定,分配不同,一定不同;第三步,对于点集相同且分配相同的路径们,他们每次走自环,走得不同,一定不同.接着观察,对于自环数一定的状态,是一样的,而且只有3种,并且他们的顺序也没有关系了(可以从组合数的角度看出),至此,对于每一种状态数量都相同且点集相同的路径,我们都可以合并,并且还可以算出合并之后的路径类在不计算内部影响下的贡献和.
好了,现在该怎么处理上面最后合并出来的每一种路径的内部贡献呢?直接在原自动机上搞,肯定不行,每一种处理一次好一些,但是还是过不了,我们考虑建立一个大图,利用邻接矩阵的次幂的性质,我们就可以直接get到每两个点之间的距离,我们只要保证在这个大图上能get到所有我们想要的信息就可以了,所以现在我们把之前的自动机合并成一个大自动机就ok了.
最后,把前两步的信息合并,就好了.
好牛逼的有限状态自动机啊,感觉就像一个两端匹配的AC自动机,而且匹配的还是子序列.
还有这个组合数学也是牛的一笔,甚至还利用组合意义合并路径.
而且那个转大图建立邻接矩阵也是超66666666666666666
(似乎还有组合数做法……看不懂……)
(把dp状态搞到有限状态自动机上似乎是套路???)
#pragma GCC optimize("O3")
#include <cstdio>
#include <cstring>
#include <algorithm>
const int P=,N=;
char s[N];
int n,m,f[N][N][],dp[N][N][N],R,G,B,S,a[N<<][N<<],temp[N<<][N<<],b[N<<][N<<];
inline void DP(){
register int i,j,l,r;
dp[][m][]=;
for(i=m;i>;--i)
for(l=,r=i;r<=m;++l,++r)
for(j=;j<=(m-i);++j){
if(!dp[l][r][j])continue;
if(s[l]==s[r]){
if(l+==r)
(dp[][][j]+=dp[l][r][j])%=P;
else if(l==r){
(dp[][][j]+=dp[l][r][j])%=P;
if(n&)(f[j][(m-j+)>>][]+=dp[l][r][j])%=P;
}else
(dp[l+][r-][j]+=dp[l][r][j])%=P;
}else{
(dp[l+][r][j+]+=dp[l][r][j])%=P;
(dp[l][r-][j+]+=dp[l][r][j])%=P;
}
}
for(i=;i<=m;++i)
(f[i][(m-i+)>>][]+=((n&)?:)*dp[][][i])%=P;
}
#define red(a) (a)
#define green(a) (R+(a))
#define blue(a) (R+G+(a))
inline void Multi1(){
memset(temp,,sizeof(temp));
register int i,j,k;
for(i=;i<=S;++i)
for(j=;j<=S;++j)
if(a[i][j])
for(k=;k<=S;++k)
if(b[j][k])
(temp[i][k]+=a[i][j]*b[j][k])%=P;
memcpy(b,temp,sizeof(b));
}
inline void Multi2(){
memset(temp,,sizeof(temp));
register int i,j,k;
for(i=;i<=S;++i)
for(j=;j<=S;++j)
if(a[i][j])
for(k=;k<=S;++k)
if(a[j][k])
(temp[i][k]+=a[i][j]*a[j][k])%=P;
memcpy(a,temp,sizeof(a));
}
inline void MUL(){
int i;
R=m,G=(m+)>>,B=G,S=R+G+B;
for(i=;i<=R;++i){
a[red(i)][red(i)]=;
if(i!=)a[red(i)][red(i-)]=;
else a[red(i)][green()]=;
}
for(i=;i<=G;++i){
a[green(i)][green(i)]=;
a[green(i)][blue(i)]=;
if(i!=G)a[green(i)][green(i+)]=;
}
for(i=;i<=B;++i)
a[blue(i)][blue(i)]=;
for(i=;i<=S;++i)b[i][i]=;
int mi=n>>;
while(mi){
if(mi&)Multi1();
Multi2(),mi>>=;
}
}
inline void CAL(){
int ans=,i,j;
for(i=;i<=R;++i)
for(j=;j<=B;++j)
if(f[i][j][])
(ans+=f[i][j][]*b[i==?green():red(i)][blue(j)])%=P;
if(n&)
for(i=;i<=R;++i)
for(j=;j<=G;++j)
if(f[i][j][])
(ans+=f[i][j][]*b[i==?green():red(i)][green(j)])%=P;
printf("%d\n",ans);
}
int main(){
scanf("%s%d",s+,&n);
m=strlen(s+),n+=m;
DP(),MUL(),CAL();
return ;
}
【Codeforces 506E】Mr.Kitayuta’s Gift&&【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化的更多相关文章
- 【CF506E】Mr. Kitayuta's Gift dp转有限状态自动机+矩阵乘法
[CF506E]Mr. Kitayuta's Gift 题意:给你一个字符串s,你需要在s中插入n个字符(小写字母),每个字符可以被插在任意位置.问可以得到多少种本质不同的字符串,使得这个串是回文的. ...
- Codeforces 506E - Mr. Kitayuta's Gift(神仙矩阵乘法)
Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%%%%%%%%%%%% u1s1 感觉这道题风格很省选( 下记 \(m=|s|\),首先探讨 \(n+m\) 为偶数的情形. ...
- Codeforces 506E Mr. Kitayuta's Gift (矩阵乘法,动态规划)
描述: 给出一个单词,在单词中插入若干字符使其为回文串,求回文串的个数(|s|<=200,n<=10^9) 这道题超神奇,不可多得的一道好题 首先可以搞出一个dp[l][r][i]表示回文 ...
- Codeforces 505A Mr. Kitayuta's Gift 暴力
A. Mr. Kitayuta's Gift time limit per test 1 second memory limit per test 256 megabytes input standa ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
- codeforces 505A. Mr. Kitayuta's Gift 解题报告
题目链接:http://codeforces.com/problemset/problem/505/A 题目意思:给出一个长度不大于10的小写英文字符串 s,问是否能通过在字符串的某个位置插入一个字母 ...
- 水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta's Gift
题目传送门 /* 水题:vector容器实现插入操作,暴力进行判断是否为回文串 */ #include <cstdio> #include <iostream> #includ ...
- codeforces Round 286# problem A. Mr. Kitayuta's Gift
Mr. Kitayuta has kindly given you a string s consisting of lowercase English letters. You are asked ...
- CodeForces 505B Mr. Kitayuta's Colorful Graph
Mr. Kitayuta's Colorful Graph Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d ...
随机推荐
- VIN码识别:毫秒间99%精准识别
科技改变生活.几年前,人工智能还仅是一个噱头,现在已逐渐融入我们的工作和生活,代替了一些重复性的.繁杂的人工劳动,在提高工作效率的同时,提升了客户体验. 车架号也叫VIN码,由17位数字和字母混合组成 ...
- Qt-Qml-播放视频-失败版-只有声音没有图像
失败版代码 import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtMultimedia ...
- XSS--编码绕过,qcms,鲶鱼cms
一.编码绕过 1)HTML进制编码 标签中的某些属性值可以使用html十进制.十六进制表示 2)JavaScript编码 JavaScript支持unicode.八进制.十六进制.十进制等 3)URL ...
- 【Set jsonObj = toJson( jsonString )】创建JSON实例
创建JSON实例: 原型: toJson( jsonString ) 说明: 创建JSON实例 返回: [JSON] 参数: jsonString [可选] 可以用json格式字符串创建实例 示例: ...
- 查看python中包的文档
核心命令:python -m pydoc 查询某包:python -m pydoc 包名 示例: C:\Users\xxx>python -m pydoc pydoc - the Python ...
- 【转】Backbone.js学习笔记(二)细说MVC
文章转自: http://segmentfault.com/a/1190000002666658 对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一) Bac ...
- canvas学习(三):文字渲染
一.绘制基本的文字: var canvas = document.getElementById("myCanvas") var ctx = canvas.getContext('2 ...
- 在线求助man page
一.举例——输入“man date” 图1 图2 图3 二.man之概述 用于:命令的使用说明 用法:man 命令 man page:执行“man 命令”后,出现的屏幕界面 补:man是manual( ...
- php mongodb扩展 其他扩展也类似
MongoDBPHP 扩展 本教程将向大家介绍如何在Linux.window.Mac平台上安装MongoDB扩展. Linux上安装 MongoDB PHP扩展 在终端上安装 你可以在linux中执行 ...
- 发生dev_queue_xmit的时候,全部都是从ip_finish_output中来的吗
也就是说啊,内核中的收发包的路径,很可能是经理driver_recv --> tcp -->driver_send这样一个过程,是个很长的路径呢...... 从dev_queue_xmit ...