2018 焦作网络赛 L Poor God Water ( AC自动机构造矩阵、BM求线性递推、手动构造矩阵、矩阵快速幂 )
题意 :
实际上可以转化一下题意
要求求出用三个不同元素的字符集例如 { 'A' 、'B' 、'C' }
构造出长度为 n 且不包含
AAA、BBB
CCC、ACB
BCA、CAC
CBC
这其中任意一个字符串的方案数
分析 :
方法一 (BM 求线性递推)
直接暴力出前 10 项的答案、然后猜它其实可以由线性递推递推而来
丢进杜教的 BM 模板里面就可以直接求出第 N 项了
实际上这个可以不用猜、这种不包含某些串的题目
如果你做过类似的、就会知道实际上是可以构造出一个矩阵然后快速幂
可以使用矩阵快速幂优化的递推方程大概都可以用 BM 求
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cassert>
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
;
ll powmod(ll a,ll b) {ll res=;a%=mod; assert(b>=); ){)res=res*a%mod;a=a*a%mod;}return res;}
// head
ll n;
namespace linear_seq {
;
ll res[N],base[N],_c[N],_md[N];
vector<int> Md;
void mul(ll *a,ll *b,int k) {
rep(i,,k+k) _c[i]=;
rep(i,,k) ,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
;i>=k;i--) if (_c[i])
rep(j,,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
rep(i,,k) a[i]=_c[i];
}
int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
ll ans=,pnt=;
int k=SZ(a);
assert(SZ(a)==SZ(b));
rep(i,,k) _md[k--i]=-a[i];_md[k]=;
Md.clear();
rep(i,,k) ) Md.push_back(i);
rep(i,,k) res[i]=;
res[]=;
while ((1ll<<pnt)<=n) pnt++;
;p--) {
mul(res,res,k);
) {
;i>=;i--) res[i+]=res[i];res[]=;
rep(j,,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
}
}
rep(i,,k) ans=(ans+res[i]*b[i])%mod;
) ans+=mod;
return ans;
}
VI BM(VI s) {
VI C(,),B(,);
,m=,b=;
rep(n,,SZ(s)) {
ll d=;
rep(i,,L+) d=(d+(ll)C[i]*s[n-i])%mod;
) ++m;
*L<=n) {
VI T=C;
ll c=mod-d*powmod(b,mod-)%mod;
);
rep(i,,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+-L; B=T; b=d; m=;
} else {
ll c=mod-d*powmod(b,mod-)%mod;
);
rep(i,,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
int gao(VI a,ll n) {
VI c=BM(a);
c.erase(c.begin());
rep(i,,SZ(c)) c[i]=(mod-c[i])%mod;
return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
int main() {
vector<int>v;
v.push_back();
v.push_back();
v.push_back();
v.push_back();
v.push_back();
v.push_back();
v.push_back();
v.push_back();
v.push_back();
v.push_back();
int nCase;
scanf("%d", &nCase);
while(nCase--){
scanf("%lld", &n);
printf() % mod);
}
}
方法二 (AC自动机构造矩阵 + 矩阵快速幂)
如果你做过 POJ 2778 那么你就能够知道这个题目
实际上将不合法的字符串丢到 AC 自动机里面去就可以构造出矩阵了
然后进行快乐的矩阵快速幂就阔以了
下面代码并非 AC 代码、只是使用 AC 自动机构造矩阵的代码
且代码大部分都使用了我写过的 POJ 2778 的代码、输入形式可看代码最后注释
#include<queue>
#include<stdio.h>
#include<string.h>
using namespace std;
;
;
;
int maxn;
];
][]; }unit, M;
mat operator * (mat a, mat b)
{
mat ret;
long long x;
; i<maxn; i++){
; j<maxn; j++){
x = ;
; k<maxn; k++){
x = (x + ((long long)a.m[i][k]%MOD * b.m[k][j]%MOD)%MOD)%MOD;
}
ret.m[i][j] = x % MOD;
}
}
return ret;
}
inline ; i<maxn; i++) unit.m[i][i] = ; }
mat pow_mat(mat a, int n)
{
mat ret = unit;
while(n){
) ret = ret * a;
a = a*a;
n >>= ;
}
return ret;
}
struct Aho{
struct StateTable{
int Next[Letter];
int fail, flag;
}Node[Max_Tot];
int Size;
queue<int> que;
inline void init(){
while(!que.empty()) que.pop();
memset(Node[].Next, , ].Next));
Node[].fail = Node[].flag = ;
Size = ;
}
inline void insert(char *s){
;
; s[i]; i++){
int idx = mp[s[i]];
if(!Node[now].Next[idx]){
memset(Node[Size].Next, , sizeof(Node[Size].Next));
Node[Size].fail = Node[Size].flag = ;
Node[now].Next[idx] = Size++;
}
now = Node[now].Next[idx];
}
Node[now].flag = ;
}
inline void BuildFail(){
Node[].fail = ;
que.push();
while(!que.empty()){
int top = que.front(); que.pop();
;///如果当前节点的Fail指针指向的节点也是末尾节点,那么这个节点也是不合法的!
; i<Letter; i++){
if(Node[top].Next[i]){
) Node[ Node[top].Next[i] ].fail = ;
else{
int v = Node[top].fail;
){
if(Node[v].Next[i]){
Node[ Node[top].Next[i] ].fail = Node[v].Next[i];
break;
}v = Node[v].fail;
}) Node[ Node[top].Next[i] ].fail = ;
}que.push(Node[top].Next[i]);
}?Node[ Node[top].fail ].Next[i]:;///多了这一句!
}
}
}
inline void BuildMatrix(){
; i<Size; i++)
; j<Size; j++)
M.m[i][j] = ;
; i<Size; i++){
; j<Letter; j++){
if(!Node[i].flag && !Node[ Node[i].Next[j] ].flag)
M.m[i][Node[i].Next[j]]++;
}
}
maxn = Size;
}
}ac;
];
int main(void)
{
mp[,
mp[,
mp[;
int n, m;
while(~scanf("%d %d", &m, &n)){
ac.init();
; i<m; i++){
scanf("%s", S);
ac.insert(S);
}
ac.BuildFail();
ac.BuildMatrix();
; i<; i++){
; j<; j++){
printf("%d ", M.m[i][j]);
}puts("");
}puts("");
init_unit();
M = pow_mat(M, n);
// for(int i=0; i<10; i++){
// for(int j=0; j<10; j++){
// printf("%d ", M.m[i][j]);
// }puts("");
// }puts("");
;
; i<ac.Size; i++)
ans = (ans + M.m[][i])%MOD;
ans %= MOD;
printf("%d\n", ans);
}
;
}
/*输入 7 和 n 然后输入字符集、就能出答案*/
/**
7 15
AAA
BBB
CCC
ACB
BCA
CAC
CBC
*/
方法三 (手动构造矩阵 + 矩阵快速幂)
首先使用各种手段抓一个聪明伶俐的队友过来
此队友需要在矩阵构造方面颇有灵性
把题目交给他翻译、构思、打代码
等待 15 分钟左右、最后即可得到 Accept
2018 焦作网络赛 L Poor God Water ( AC自动机构造矩阵、BM求线性递推、手动构造矩阵、矩阵快速幂 )的更多相关文章
- ACM-ICPC 2018 焦作网络赛
题目顺序:A F G H I K L 做题链接 A. Magic Mirror 题意:判断 给出的 字符串 是否等于"jessie",需要判断大小写 题解:1.用stl库 tolo ...
- ACM-ICPC 2018 焦作赛区网络预赛 L Poor God Water(矩阵快速幂,BM)
https://nanti.jisuanke.com/t/31721 题意 有肉,鱼,巧克力三种食物,有几种禁忌,对于连续的三个食物:1.这三个食物不能都相同:2.若三种食物都有的情况,巧克力不能在中 ...
- 2018 焦作网络赛 G Give Candies ( 欧拉降幂 )
题目链接 题意 : 给出 N 个糖果.老师按顺序给 1~N 编号的学生分配糖果.每个学生要么不分.要么最少分一个.且由于是按顺序发放.那么对于某个有分到糖果的编号为 i 的学生.则 1~(i-1) 这 ...
- 2018焦作网络赛 - Poor God Water 一道水题的教训
本题算是签到题,但由于赛中花费了过多的时间去滴吧格,造成了不必要的浪费以及智商掉线,所以有必要记录一下坑点 题意:方格从1到n,每一格mjl可以选择吃鱼/巧克力/鸡腿,求走到n格时满足 1.每三格不可 ...
- 2018 焦作网络赛 K Transport Ship ( 二进制优化 01 背包 )
题目链接 题意 : 给出若干个物品的数量和单个的重量.问你能不能刚好组成总重 S 分析 : 由于物品过多.想到二进制优化 其实这篇博客就是存个二进制优化的写法 关于二进制优化的详情.百度一下有更多资料 ...
- 2018焦作网络赛-E- Jiu Yuan Wants to Eat
题目描述 You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, s ...
- 2018焦作网络赛Mathematical Curse
题意:开始有个数k,有个数组和几个运算符.遍历数组的过程中花费一个运算符和数组当前元素运算.运算符必须按顺序花费,并且最后要花费完.问得到最大结果. 用maxv[x][y]记录到第x个元素,用完了第y ...
- 2018焦作网络赛Give Candies
一开始忽略了欧拉定理指数部分是modphi(n-1)没有memset,减法后面没加0:
- 2018南京网络赛L题:Magical Girl Haze(最短路分层图)
题目链接:https://nanti.jisuanke.com/t/31001 解题心得: 一个BZOJ的原题,之前就写过博客了. 原题地址:https://www.lydsy.com/JudgeOn ...
随机推荐
- [python] 正则表达式细节
1.零宽断言 所谓零宽断言就是并不去真正的匹配字符串文本,而仅仅是匹配对应的位置. 正则表达式中有很多这样的断言,常见的如匹配字符串或者行的起始位置 ^ 和 /A,匹配字符串或者行的末尾 $ 和 /Z ...
- PTA(Basic Level)1015.德才论
宋代史学家司马光在<资治通鉴>中有一段著名的"德才论":"是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得圣人,君子 ...
- Python 入门 之 类的三大关系(依赖 / 组合/ 继承关系)
Python 入门 之 类的三大关系(依赖 / 组合/ 继承关系) 在面向对象的中,类与类之间存在三种关系:依赖关系.组合关系.继承关系. 1.依赖关系:将一个类的类名或对象当做参数传递给另一个函数被 ...
- SqlSugar
SqlSugar 官网 SqlSugar 源码 SqlSugar NuGet
- 深入理解hadoop之机架感知
深入理解hadoop之机架感知 机架感知 hadoop的replication为3,机架感知的策略为: 第一个block副本放在和client所在的datanode里(如果client不在集群范围内, ...
- 让图表的Y轴 产生几个刻度距离
动态设置max 查看官网 写入方法 获取到你数据最大值 然后+个100
- java笔记web
1,spring请求同,返回同一个界面 Dubbo消费者无法连接到生产者提供的服务?内网IP? https://blog.csdn.net/xlgen157387/article/details/52 ...
- 让虚拟机中的MySQL可以被主机访问
1.VirtualBox对Ubuntu系统进行设置,“网络”选择“桥接网卡” 2.安装MYSQL服务器 sudo su; apt-get intall mysql-server 3.赋予远程访问的 ...
- 修改MySQL表中自增编号
alter table 表名 AUTO_INCREMENT = 值 例:
- MySQL配置文件my.cnf中文详解
#BEGIN CONFIG INFO #DESCR: 4GB RAM, 只使用InnoDB, ACID, 少量的连接, 队列负载大 #TYPE: SYSTEM #END CONFIG INFO # # ...