Codeforces 506E Mr. Kitayuta's Gift (矩阵乘法,动态规划)
描述:
给出一个单词,在单词中插入若干字符使其为回文串,求回文串的个数(|s|<=200,n<=10^9)
这道题超神奇,不可多得的一道好题
首先可以搞出一个dp[l][r][i]表示回文串左边i位匹配到第l位,右边i位匹配到第r位的状态数,可以发现可以用矩阵乘法优化(某人说看到n这么大就一定是矩阵乘法了= =)
但这样一共有|s|^2个节点,时间复杂度无法承受
我们先把状态树画出来:例如add
可以发现是个DAG
我们考虑把单独的每条链拿出来求解,那么最多会有|s|条不同的链,链长最多为|s|,时间复杂度为O(|s|^4log n)还是得跪
好像没什么思路了对吧= =(我第一步转化就没想到了= =)
我们考虑记有24个自环的为n24,25个自环的为n25,可以发现n24+n25*2=|s|或|s|+1也就是说对于一个确定的n24,一定有一个确定的n25
那么这样构图:
可以发现所有状况都被包括进来了!!!
那么一共有2|s|个节点,时间复杂度降了一个|s|,看上去好像还是不行
压常数= =
可以发现这个是棵树,也就是说如果按拓扑序编号的话,到时的矩阵左下角将是什么都没有的
那么就直接for i = 1 to n j = i to n k=i to j 就行了 = =
总结下吧
这道题为何神奇呢
首先它把一个DAG的图拆成了若干条相似的链
然后它又把这些链和成了一个更和谐的图
最后再观察题目性质得到一个比较神奇的优化方法
这给了我们什么启迪呢= =
首先遇到某些DAG我们可以考虑拆成若干条相似的链
遇到某些链我们可以考虑把他们合成一个图
最重要的是,还是得参透题目的性质
这道题基本都是依靠题目的性质到达下一步的,只有真正读懂读透这道题,我们才能想出更好的解法
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 410
#define mod 10007
typedef int ll;
struct marix{
int r,c;ll a[maxn][maxn];
inline void init(int x){r=c=x;for (int i=;i<=x;i++) a[i][i]=;}
}x,y;
inline void muti(marix &ans,const marix x,const marix y){
ans.r=ans.c=x.r;
for (int i=;i<=x.r;i++)
for (int j=i;j<=y.c;j++) {
int tmp=;
for (int k=i;k<=j;k++)
(tmp+=x.a[i][k]*y.a[k][j])%=mod;
ans.a[i][j]=tmp;
}
}
inline void power(marix &ans,marix x,int y) {
ans.init(x.r);
for (;y;y>>=) {
if (y&) muti(ans,ans,x);
muti(x,x,x);
}
}
ll f[][][];
char s[maxn];
inline ll calc(int l,int r,int x) {
ll &u=f[x][l][r];
if (u!=-) return u;
u=;
if (l==r) return u=x==;
if (s[l]==s[r]) {
if (l+==r) return u=x==;
return u=calc(l+,r-,x);
}
if (x>) return u=(calc(l+,r,x-)+calc(l,r-,x-))%mod;
return u;
}
int main(){
int n,m;
memset(f,-,sizeof(f));
scanf("%s",s+);
scanf("%d",&n);
m=strlen(s+);
n+=m;
int l=(n+)/,n24=m-,n25=(m+)/,n26=n25;
x.r=x.c=n24+n25+n26;
for (int i=;i<=n24;i++) x.a[i][i]=,x.a[i][i+]=;
for (int i=n24+;i<=n25+n24;i++) x.a[i][i]=,x.a[i][i+n25]=;
for (int i=n24+n25+;i<=n25+n24+n26;i++) x.a[i][i]=;
for (int i=n24+;i<n25+n24;i++) x.a[i][i+]=;
marix y;
power(y,x,l-);
muti(x,y,x);
ll ans;
for (int i=;i<=n24;i++) {
int j=(m-i+)/,k=l-i-j;
if (k<) continue;
ll sum=calc(,m,i);
(ans+=sum*x.a[n24-i+][n24+j+n25]%mod)%=mod;
if ((n&)&&(m-i&^))
(ans=ans-sum*y.a[n24-i+][n24+j]%mod+mod)%=mod;
}
printf("%d\n",ans);
return ;
}
Codeforces 506E Mr. Kitayuta's Gift (矩阵乘法,动态规划)的更多相关文章
- Codeforces 506E - Mr. Kitayuta's Gift(神仙矩阵乘法)
Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%%%%%%%%%%%% u1s1 感觉这道题风格很省选( 下记 \(m=|s|\),首先探讨 \(n+m\) 为偶数的情形. ...
- 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 ...
- codeforces 505A. Mr. Kitayuta's Gift 解题报告
题目链接:http://codeforces.com/problemset/problem/505/A 题目意思:给出一个长度不大于10的小写英文字符串 s,问是否能通过在字符串的某个位置插入一个字母 ...
- 【CF506E】Mr. Kitayuta's Gift dp转有限状态自动机+矩阵乘法
[CF506E]Mr. Kitayuta's Gift 题意:给你一个字符串s,你需要在s中插入n个字符(小写字母),每个字符可以被插在任意位置.问可以得到多少种本质不同的字符串,使得这个串是回文的. ...
- 水题 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 ...
- codeforces 505B Mr. Kitayuta's Colorful Graph(水题)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Mr. Kitayuta's Colorful Graph Mr. Kitayut ...
- [Codeforces 505C]Mr. Kitayuta, the Treasure Hunter
Description The Shuseki Islands are an archipelago of 30001 small islands in the Yutampo Sea. The is ...
随机推荐
- PHP内核变量存储
PHP作为一门弱类型语言,其变量类型可任意改变.而C作为PHP的底层实现,是通过结构及联合来实现PHP变量的弱类型特性的.在PHP源码中,Zend/zend.h文件有关于PHP变量的结构定义. 01 ...
- CSS实现导航条Tab切换的三种方法
前面的话 导航条Tab在页面中非常常见,本文说详细介绍CSS实现导航条Tab的三种方法 布局 根据上图所示,先规定几个定义,上图的模块整体叫做导航,由导航标题和导航内容组成.要实现上图所示的布 ...
- bzoj3551
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 877 Solved: 297[Submit][S ...
- CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本定时任务方式实现mysql数据库服务随机自动启动
CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本定时任务方式实现mysql数据库服务随机自动启动1.关于mysql?MySQL是一个关系型数据库管理 ...
- Aaron Swartz – 互联网天才开挂的人生历程:每时每刻都问自己,现在这世界有什么最重要的事是我能参与去做的?
Aaron说的一句话让我挺有感触的-- 相信你应该真的每时每刻都问自己,现在这世界有什么最重要的事是我能参与去做的? 如果你没在做那最重要的事,那又是为什么? 1986年11月8日,有个叫Aaron ...
- 一个完整的PHP类包含的七种语法说明
类中的七种语法说明 -属性 -静态属性 -方法 -静态方法 -类常量 -构造函数 -析构函数 <?php class Student { // 类里的属性.方法和函数的访问权限有 (函数和方法是 ...
- js原生继承之——类式继承实例(推荐使用)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- JavaScript 模拟策略模式
/** * 模拟一个接口,其方法会抛出异常: */ function FlyInter () {} FlyInter.prototype.fly = function() { throw '实现这个接 ...
- Sublime3 中在行尾增加一个分号的方法
1,自己录制一个宏,名称为add comma to end.sublime-macro,宏内容如下: [ { "args": { "extend": false ...
- FlashPlayer11 异步解码 Bitmap
Flash Player 11引入了一个全新的功能是异步解码位图的功能,这个功能对某些类型的Flash应用会很有效,尤其是需要加载大分辨率的位图的相册或游戏会有显著效果,使用位图图像时,可以异步解码和 ...