【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 ...
随机推荐
- 基于Python的接口自动化
第一步 Python的安装配置 打开官网: https://www.python.org/downloads/ 目前官网上已经更新到3.6.1啦,有两个版本,大家可以按自己喜欢的去下载,我自己选择的是 ...
- hello-jni Android.mk文件简析
#删除旧变量 LOCAL_PATH := $(call my-dir) #返回当前目录 include $(CLEAR_VARS) #删除旧变量 #设置新变量 LOCAL_MODULE := hell ...
- ## 在webapp上使用input:file, 指定capture属性调用默认相机,摄像,录音功能
在iOS6下开发webapp,使用inputz之file,很有用 <input type="file" accept="image/*" capture= ...
- 204. Singleton
Description Singleton is a most widely used design pattern. If a class has and only has one instance ...
- “Hello World”团队第一周博客汇总
时间:2017-10-13——2017-10-19 Scrum会议: 会议要求博客:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/1 ...
- Thunder团队第一周 - Scrum会议4
Scrum会议4 小组名称:Thunder 项目名称:爱阅app Scrum Master:代秋彤 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...
- c# windows service 程序
service服务程序:可以长时间运行可执行应用程序.没有用户界面.可以自动启动和手动启动.适用于在服务器上或需要干扰其他工作的用户可以在同一台计算机上长时间的运行此功能. C#创建service服务 ...
- P4编程环境搭建遇到的问题与解决方法
在经历了无数的折腾之后,算是折腾,最后采用的是陈翔学长的脚本加上可爱的shell调整装好的. 链接:p4Install 也许是ubuntu18.04的问题,也有可能是我自己把这个系统折腾的有点杂乱的原 ...
- python学习摘要(2)--基本数据类型
python申请存储空间是动态的.变量如同指针一样指向存储空间.多个变量会指向同一个存储空间(节省空间).当变量改变时,原来的地址单元并不会马上释放.(引用计数自行回收) c/c++根基性语言,想要什 ...
- java — JVM调优
数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型.基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对象本身, ...