[ACM-ICPC 2018 焦作赛区网络预赛][L.Poor God Water][AC自动机(伪)+矩阵快速幂]

题意

T组数据,构造长度为N的串,不含111,222,333,132,231,313,323字串的方案数

数据范围:T \leq 1000, 1 \leq N \leq 10^{10}

分析

AC自动机构造矩阵,但我不会(目前)_(°:з」∠)_

可以将合法的三元串xyz看作xy->yz,这就形成了一个转移关系那么11->11就是非法的,13->32也是非法的

这就可以填充一个9*9的矩阵A,A^n中元素a_n[i][j]表示从i转移到j的合法种数,A^n所有元素和即为答案。

PS:比赛时丢脸的用trie树手写了一个29*29的矩阵(把用111->11,21->213这种来表示转移),在线丢脸ε=ε=ε=ε=ε=ε=┌(; ̄◇ ̄)┘

#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
using namespace std;

using LL = long long;
const int MOD = 1e9 + 7;
struct matrix {
  LL num[55][55], len;
  void init(){
    memset(num, 0, sizeof(num));
    len = 0;
  }
  matrix operator *(const matrix &a){
    matrix res;
    res.init(), res.len = a.len;
    for(int i = 0; i < len; i++)
      for(int j = 0; j < len; j++)
        for(int k = 0; k < len; k++)
          res.num[i][j] += (num[i][k] * a.num[k][j]) % MOD, res.num[i][j] %= MOD;
    return res;
  }
  void getprint(){
    for(int i = 0; i < len; i++){
      for(int j = 0; j < len; j++)
        printf("%3lld ", num[i][j]);
      printf("\n");
    }
  }
} A;
matrix qpow_matraix(matrix x, LL n);
LL T, N;

int main(){
  A.init(), A.len = 9;
  int i, j;
  for(i = 0; i < 9; i++)
    for(j = 0; j < 3; j++) A.num[i][j + i % 3 * 3] = 1;
  A.num[0][0] = 0;//11->11
  A.num[2][7] = 0;//13->32
  A.num[4][4] = 0;//22->22
  A.num[5][6] = 0;//23->31
  A.num[6][2] = 0;//31->13
  A.num[7][5] = 0;//32->23
  A.num[8][8] = 0;//33->33
  //A.getprint();
  cin >> T;
  while(T--){
    cin >> N;
    if(N == 1){cout << 3 << endl; continue;}
    else if(N == 2){cout << 9 << endl; continue;}
    LL ans = 0;
    matrix tmp = qpow_matraix(A, N - 2);
    for(i = 0; i < tmp.len; i++)
      for(j = 0; j < tmp.len; j++) ans += tmp.num[i][j], ans %= MOD;
    cout << ans << endl;
  }
  return 0;
}

matrix qpow_matraix(matrix X, LL n){
  matrix E;
  E.init(), E.len = X.len;
  int i;
  for(i = 0; i <= E.len; i++) E.num[i][i] = 1;
  while(n){
    if(n & 1) E = E * X;
    X = X * X;
    n >>= 1;
  }
  return E;
}

猜你喜欢

转载自blog.csdn.net/Hardict/article/details/82718051