【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 ...
随机推荐
- C 进制 类型说明符 位运算 char类型
一 进制 1. 什么是进制 是一种计数的方式 数值的表示形式 2. 二进制 1> 特点: 只有0和1 逢2进1 2> 书写格式: 0b或者0B开头 3> %d 以带符号的十进制形式输 ...
- 如何搭建本地svn服务器和搭建本地Git服务器
搭建git本地服务器使用的软件有很多,例如:gitlab,gitblit,gitbucket,gogs,gitolite,具体比较:http://softlab.sdut.edu.cn/blog/su ...
- UniMelb Comp30022 IT Project (Capstone) - 1.Android入门
1. Android入门 Android系统架构 Android系统:四层架构.五块区域 1. Linux内核层 Linux Kernel:为Android设备的硬件提供了底层驱动 2. 系统运行库层 ...
- java扫描控制台输入
由于因最近练习算法的需要,加上API文档中翻译的太过模糊,做了一些小测试,算是武断的记下一些个人结论. Scanner cin = new Scanner(System.in); 对于cin.next ...
- 并发HashMap的put操作引起死循环
今天研读Java并发容器和框架时,看到为什么要使用ConcurrentHashMap时,其中有一个原因是:线程不安全的HashMap, HashMap在并发执行put操作时会引起死循环,是因为多线程会 ...
- Centos7添加静态路由
本文摘取自 Centos7系统配置上的变化(二)网络管理基础 一.ip route显示和设定路由 1.显示路由表 [root@centos7 ~]# ip route show default via ...
- LeetCode 98——验证二叉搜索树
1. 题目 2. 解答 2.1. 方法一 我们初始化根节点的范围为长整形数据的最小最大值 \([LONG\_MIN,LONG\_MAX]\),则其左子节点的取值范围为 \([LONG\_MIN,根节点 ...
- FZU 1844 Earthquake Damage(最大流最小割)
Problem Description Open Source Tools help earthquake researchers stay a step ahead. Many geological ...
- Thunder团队第一周 - Scrum会议2
Scrum会议2 小组名称:Thunder 项目名称:待定 Scrum Master:李传康 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康(M ...
- 找bug——加分作业
bug1:while循环中的*des++ =*src++; 不能这么写吧... bug2:maxSize没有定义 暂时看到这么多