【GDOI2016模拟3.9】暴走的图灵机
题目
分析
我们发现当两个字符串合并时,a0、a1表示左右两个字符串中有多少个T,C表示合并处新增的T的个数,那么
a0=a1
a1=a0+a1+C
令s0和s1表示左右手两个字符串,那么每一次操作后左右手字符串分别为:
操作次数 左手 右手
0 s0 s1
1 s1 s0s1
2 s0s1 s1s0s1
3 s1s0s1 s0s1s1s0s1
4 s0s1s1s0s1 s1s0s1s0s1s1s0s1
5 s1s0s1s0s1s1s0s1 s0s1s1s0s1s1s0s1s0s1s1s0s1
···
然后我们发现,从第1次操作以后,每次合并处是以s1s1和s1s0为一个循环。也就是说当|s0|>=m-1时,我们用KMP处理出a0、a1以及s1s1和s1s0合并时新增T的个数,然后O(N)递推一遍就可以了。
但是n<=10^9,只能拿60分。
因为递推时有循环,所以就可以构造矩阵,打个矩阵快速幂O(logN)。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
using namespace std;
char s[30000],s1[30000],s2[30000],t[30000];
long long n,m,tot,ans,mo,next[30000],f[2][5],lens=1,lens1=1,nn,nnn;
long long jz[5][5]=
{
{0,0,0,0,0},
{0,1,1,0,0},
{0,1,2,0,0},
{0,1,1,1,0},
{0,0,1,0,1}
},b[5][5];
long long getnext()
{
long long i,j,k;
j=0;
for(i=2;i<=m;i++)
{
while(j>0 && t[j+1]!=t[i]) j=next[j];
if(t[j+1]==t[i]) j++;
next[i]=j;
}
}
long long kmp()
{
long long i,j,k;
getnext();
j=0;
for(i=1;i<=lens;i++)
{
while(j>0 && t[j+1]!=s[i]) j=next[j];
if(t[j+1]==s[i]) j++;
if(j==m) f[0][1]++;
}
j=0;
for(i=1;i<=lens1;i++)
{
while(j>0 && t[j+1]!=s1[i]) j=next[j];
if(t[j+1]==s1[i]) j++;
if(j==m) f[0][2]++;
}
}
long long kmp1()
{
long long i,j,k;
k=0;
for(i=lens-m+2;i<=lens;i++)
s2[++k]=s[i];
for(i=1;i<=m-1;i++)
s2[++k]=s1[i];
j=0;
for(i=1;i<=m+m-2;i++)
{
while(j>0 && t[j+1]!=s2[i]) j=next[j];
if(t[j+1]==s2[i]) j++;
if(j==m) f[0][0]++;
}
k=0;
for(i=lens1-m+2;i<=lens1;i++)
s2[++k]=s1[i];
for(i=1;i<=m-1;i++)
s2[++k]=s[i];
j=0;
for(i=1;i<=m+m-2;i++)
{
while(j>0 && t[j+1]!=s2[i]) j=next[j];
if(t[j+1]==s2[i]) j++;
if(j==m) f[0][3]++;
}
k=0;
for(i=lens1-m+2;i<=lens1;i++)
s2[++k]=s1[i];
for(i=1;i<=m-1;i++)
s2[++k]=s1[i];
j=0;
for(i=1;i<=m+m-2;i++)
{
while(j>0 && t[j+1]!=s2[i]) j=next[j];
if(t[j+1]==s2[i]) j++;
if(j==m) f[0][4]++;
}
}
long long mi()
{
long long x=0,y=1,i,j,k;
while(nn>0)
{
if(nn&1==1)
{
for(i=1;i<=4;i++)
{
f[x][i]=0;
for(j=1;j<=4;j++)
f[x][i]=(f[x][i]+(f[y][j]*jz[j][i])%mo)%mo;
}
x=y;
y=1-y;
}
for(i=1;i<=4;i++)
for(j=1;j<=4;j++)
{
b[i][j]=0;
for(k=1;k<=4;k++)
{
b[i][j]=(b[i][j]+(jz[i][k]*jz[k][j])%mo)%mo;
}
}
for(i=1;i<=4;i++)
for(j=1;j<=4;j++)
{
jz[i][j]=b[i][j];
}
nn/=2;
}
return y;
}
int main()
{
scanf("%d%d%d",&n,&m,&mo);
scanf("%s",t+1);
s[1]='0';
s1[1]='1';
long long i,j,k,l,x,y;
for(j=1;j<=n;j++)
{
for(i=1;i<=lens1;i++)
s2[i]=s1[i];
for(i=1;i<=lens;i++)
s1[i]=s[i];
for(i=1;i<=lens1;i++)
{
s1[lens+i]=s2[i];
}
for(i=1;i<=lens1;i++)
s[i]=s2[i];
x=lens1;
lens1+=lens;
lens=x;
y=j;
if(lens>=m)
break;
}
kmp();
if(n==y)
{
printf("%d\n",f[0][1]%mo);
return 0;
}
kmp1();
f[1][1]=(f[0][2])%mo;
f[1][2]=(f[0][1]+f[0][2]+f[0][0])%mo;
f[1][3]=(f[0][3])%mo;
f[1][4]=(f[0][4])%mo;
n-=y+1;
x=1;
y=0;
y=f[1][3];
n-=0;
nnn=n%2;
nn=n/2;
x=mi();
if(nnn==1)
{
printf("%d\n",(f[x][2])%mo);
return 0;
}
else
printf("%d\n",f[x][1]%mo);
}
【GDOI2016模拟3.9】暴走的图灵机的更多相关文章
- 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)
[GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...
- 【GDOI2016模拟3.16】幂(容斥 + 模型复杂转化)
[GDOI2016模拟3.16]幂 \(X\in[1,A],Y\in[1,B]\),问:\(x^y\)的不用取值个数. \(A,B\)都是\(10^9\)级别. 然后我们开搞. 首先,假设一个合法的\ ...
- 【GDOI2016模拟4.22】总结
前言 早上,一进机房,发现所有人神情严肃,一股(\(da\))(\(ba\))场的气氛迎面扑来,我一下子意识到:nothing good! 这场比赛结果不是很好,50分: 第一题:感觉上是个神奇的匹配 ...
- 【GDOI2016模拟3.10】习用之语
前言 这道题看上去很水,结果我在比赛上浪费了N多时间在上面,但还是没AC.比赛结束后发现:实际上这道题还是是大水. 题目 分析 设字符串c1c2c3c4,其中c1.c2.c3.c4={'0'~'9', ...
- 【JZOJ4461】【GDOI2016模拟4.21】灯塔 分治
题面 GDOI是一个地处丘陵的小国,为了边防建设,国王希望在国界线上的某一座山峰上建立一座灯塔,照亮整个边界.而灯塔建设的调研工作,就交给了你. GDOI的国境线上有N座连续的山峰,其中第i座的高度是 ...
- AI数学基础之:确定图灵机和非确定图灵机
目录 简介 图灵机 图灵机的缺点 等效图灵机 确定图灵机 非确定图灵机 简介 图灵机是由艾伦·麦席森·图灵在1936年描述的一种抽象机器,它是人们使用纸笔进行数学运算的过程的抽象,它肯定了计算机实现的 ...
- 操作系统之CPU管理的直观想法
计算机:是工具,帮助解决实际问题 操作系统,是为了方便使用硬件 计算机模型: 图灵机,模拟人类计算 起初的图灵机就像一个只会做一道菜的厨师 通用图灵机,核心是设置控制器动作(修改控制器),把逻辑读入控 ...
- p,np,npc,np难问题,确定图灵机与非确定图灵机
本文转自豆瓣_燃烧的影子 图灵机与可计算性 图灵(1912~1954)出生于英国伦敦,19岁进入剑桥皇家学院研究量子力学和数理逻辑.1935年,图灵写出了"论高斯误差函数"的论文, ...
- 图灵机(转自wiki)
图灵机(英语:Turing machine),又称确定型图灵机,是英国数学家艾伦·图灵于1936年提出的一种抽象计算模型,其更抽象的意义为一种数学逻辑机,可以看作等价于任何有限逻辑数学过程的终极强大逻 ...
随机推荐
- 查看dll中的函数(方法)
https://jingyan.baidu.com/article/5553fa82b953b365a23934b7.html 查看dll中的函数(方法) 听语音 | 浏览:2004 | 更新:201 ...
- .net通用签名方法 webapi签名方法
验证签名方法 [HttpGet] public HttpResponseMessage LockRegister(string 参数1, int 参数2, string 参数3, string 参数4 ...
- 应用安全 - CMS - PHPCMS漏洞汇总
CVE-2011-0644 Date: 2011.1 类型: /flash_upload.php SQL注入 影响版本:phpCMS 2008 V2 PHPCMS PHPCMS通杀XSS 在我要报错功 ...
- Linux 后台执行python或者java代码的命令
1.nohup 命令操作后台执行程序 后台启动 nohup python app.py params1 > nohup.out >& & 查看后台进程启动 jobs -l ...
- js函数的定义和调用
函数的定义 函数使用function 声明,后跟一组参数以及函数体,语法如下: function functionName([age0,age1,......argn]){ statements } ...
- Vue 实现手动刷新组件
Vue 实现手动刷新组件:https://www.jianshu.com/p/742142dc95f3
- C++中的函数重载分析(一)
1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...
- javascript学习笔记--经典继承、组合继承、原型式继承、寄生继承以及寄生组合继承
经典继承 js中实现经典继承的方式是通过构造函数来实现的,即在子类中对父类调用call方法. function Geometric() { this.time = ""; this ...
- vue-split-table【表格合并和编辑插件】
前言 vue-split-table应用的效果图 vue-split-table开源地址,欢迎star,现在已经开源和同步到npm上轻松搞定表格拆分或者合并,编辑,再也不怕被产品怼啦 1.核心源码分析 ...
- 结构体指针,C语言结构体指针详解
结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针. 指向结构体变量的指针 前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针. 前面讲过,& ...