题目链接

题意 :

实际上可以转化一下题意

要求求出用三个不同元素的字符集例如 { '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求线性递推、手动构造矩阵、矩阵快速幂 )的更多相关文章

  1. ACM-ICPC 2018 焦作网络赛

    题目顺序:A F G H I K L 做题链接 A. Magic Mirror 题意:判断 给出的 字符串 是否等于"jessie",需要判断大小写 题解:1.用stl库 tolo ...

  2. ACM-ICPC 2018 焦作赛区网络预赛 L Poor God Water(矩阵快速幂,BM)

    https://nanti.jisuanke.com/t/31721 题意 有肉,鱼,巧克力三种食物,有几种禁忌,对于连续的三个食物:1.这三个食物不能都相同:2.若三种食物都有的情况,巧克力不能在中 ...

  3. 2018 焦作网络赛 G Give Candies ( 欧拉降幂 )

    题目链接 题意 : 给出 N 个糖果.老师按顺序给 1~N 编号的学生分配糖果.每个学生要么不分.要么最少分一个.且由于是按顺序发放.那么对于某个有分到糖果的编号为 i 的学生.则 1~(i-1) 这 ...

  4. 2018焦作网络赛 - Poor God Water 一道水题的教训

    本题算是签到题,但由于赛中花费了过多的时间去滴吧格,造成了不必要的浪费以及智商掉线,所以有必要记录一下坑点 题意:方格从1到n,每一格mjl可以选择吃鱼/巧克力/鸡腿,求走到n格时满足 1.每三格不可 ...

  5. 2018 焦作网络赛 K Transport Ship ( 二进制优化 01 背包 )

    题目链接 题意 : 给出若干个物品的数量和单个的重量.问你能不能刚好组成总重 S 分析 : 由于物品过多.想到二进制优化 其实这篇博客就是存个二进制优化的写法 关于二进制优化的详情.百度一下有更多资料 ...

  6. 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 ...

  7. 2018焦作网络赛Mathematical Curse

    题意:开始有个数k,有个数组和几个运算符.遍历数组的过程中花费一个运算符和数组当前元素运算.运算符必须按顺序花费,并且最后要花费完.问得到最大结果. 用maxv[x][y]记录到第x个元素,用完了第y ...

  8. 2018焦作网络赛Give Candies

    一开始忽略了欧拉定理指数部分是modphi(n-1)没有memset,减法后面没加0:

  9. 2018南京网络赛L题:Magical Girl Haze(最短路分层图)

    题目链接:https://nanti.jisuanke.com/t/31001 解题心得: 一个BZOJ的原题,之前就写过博客了. 原题地址:https://www.lydsy.com/JudgeOn ...

随机推荐

  1. luoguP3390(矩阵快速幂模板题)

    链接:https://www.luogu.org/problemnew/show/P3390 题意:矩阵快速幂模板题,思路和快速幂一致,只需提供矩阵的乘法即可. AC代码: #include<c ...

  2. spring笔记3路径跳转

    ---恢复内容开始--- 页面跳转 <!--forward直接跳转--><jsp:forward page="pages/admin/member/add_pre.acti ...

  3. 如何让 node 运行 es6 模块文件,及其原理

    如何让 node 运行 es6 模块文件,及其原理 最新版的 node 支持最新版 ECMAScript 几乎所有特性,但有一个特性却一直到现在都还没有支持,那就是从 ES2015 开始定义的模块化机 ...

  4. Mac OS 下定制终端颜色

    方法 有五种方法, 参考网站,我使用的是 Oh My Zsh 方案一:(通过 .bash_profile 文件自定制) 方案二:(也是修改 ~/.bash_profile) 方案三:(三方插件 Oh ...

  5. 前端 使用localStorage 和 Cookie相结合的方式跨页面传递参数

    A页面 html代码: 姓名:<input type="text" id="name1"> 年龄:<input type="text ...

  6. 106、Label 控制 Service的位置 (Swarm13)

    参考https://www.cnblogs.com/CloudMan6/p/8038799.html   上一节我们讨论了 Service部署的两种模式,global mode 和 replicate ...

  7. Android官方网站!

    Android官方网站,所有Android相关文档.官方工具.示例,全部都在上面!! http://www.android.com/

  8. 【转】CNN+BLSTM+CTC的验证码识别从训练到部署

    [转]CNN+BLSTM+CTC的验证码识别从训练到部署 转载地址:https://www.jianshu.com/p/80ef04b16efc 项目地址:https://github.com/ker ...

  9. tomcat性能优化,内存优化和并发线程连接优化

    今天被一同事问到tomcat和内存优化的问题,而网上的资料基本都是来回copy,所以抽时间随便写点.文章中设置的参数都是一个随便写的,具体的还要根据自己的情况来定. 1.内存优化: 说到tomcat不 ...

  10. mysql prompt的用法详解

    prompt命令可以在mysql提示符中显示当前用户.数据库.时间等信息 代码如下: mysql -uroot -p --prompt="\\u@\\h:\\d \\r:\\m:\\s> ...