题意就不说了。

分析:折腾好几天自己写的代码还是看了别人代码后发现几乎没什么复杂度的差别,可是就是一直超时,后来干脆照着别人写啊,一直WA,就在准备放弃干脆先写这篇博客的时候,又看了一眼WA的代码,发现一个中间变量没有取模直接爆掉了。终于AC了,做了好几天。

思路:对所有单词建立AC自动机,那么每个节点j转移到下一个节点k有方程:dp[i+1][k] =sum{dp[i][j]*Get},表示第i+1步位于k节点,并且由j节点转移过来,其中 Get =  ∏prime[i]*(len[i]+j)。 关键在于这里,结果是要对  179*173*163 取模, 而且Get函数和j有关,也就是走到了第j步,可以先将结果对179, 173, 163取模,然后利用中国剩余定理求出最终结果。

中国剩余定理,可以利用扩展欧几里得求出。我还是不知道我超时的原因,真是给跪了!!!!

别人代码也差不多4000+ms,我写的可能更搓了。

代码:

 #pragma comment(linker, "/STACK:16777216")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#define inf 0x0f0f0f0f
#define in freopen("data.txt", "r", stdin);
#define pb push_back using namespace std;
typedef long long LL; const int maxnode = ;
const int sigma_size = ;
int prime[maxnode], vis[]; void getPrime() {
int cnt = ;
for(int i = ; i < && cnt <= ; i++) {
if(!vis[i]) prime[++cnt] = i;
for(int j = i*i; j < ; j += i)
vis[j] = ;
}
} struct Node {
int len, n;
Node(int len, int n): len(len), n(n) {}
};
int ch[maxnode][sigma_size], sz, f[maxnode]; vector<Node> vec[maxnode];
struct Matrix {
int a[][];
} xx[], E0;;
void maMul(Matrix x, Matrix y, Matrix &res, int mod) {
for(int i = ; i < sz; i++)
for(int j = ; j < sz; j++) {
res.a[i][j] = ;
for(int k = ; k < sz; k++) {
res.a[i][j] += x.a[i][k]*y.a[k][j]%mod;
if(res.a[i][j] >= mod)
res.a[i][j] -= mod;
}
}
}
struct AC { void init() {
sz = ;
memset(ch[], , sizeof ch[]);
vec[].clear();
}
int idx(char ch) {
return ch - 'A';
}
void insert(char *s, int x) {
int u = , len = ;
for(int i = ; s[i]; i++, len++) {
int c = idx(s[i]);
if(!ch[u][c]) {
memset(ch[sz], , sizeof ch[sz]);
vec[sz].clear();
ch[u][c] = sz++;
}
u = ch[u][c];
}
vec[u].pb(Node(len, prime[x]));
}
void getFail() {
queue<int> q;
f[] = ;
for(int c = ; c < sigma_size; c++) {
int u = ch[][c];
if(u) {
f[u] = ;
q.push(u);
}
}
while(!q.empty()) {
int r = q.front();
q.pop();
for(int c = ; c < sigma_size; c++) {
int u = ch[r][c];
if(!u) {
ch[r][c] = ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while(v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
}
}
}
void getMat(int x, int mod) {
for(int i = ; i < sz; i++) for(int j = ; j < sz; j++) xx[x].a[i][j] = ;
for(int u = ; u < sz; u ++)
for(int c = ; c < sigma_size; c++) {
int v = ch[u][c];
int tv = v;
int res = ;
while(tv) {
for(int i = ; i < (int)vec[tv].size(); i++) {
(res *= ((LL)(vec[tv][i].len+x)*vec[tv][i].n%mod))%=mod;
}
tv = f[tv];
}
xx[x].a[v][u] += res;
if(xx[x].a[v][u] >= mod) xx[x].a[v][u] -= mod;
}
}
} solver; int N;
LL L;
int M[] = {, , };
int ans[], a[];
int exgcd(int a, int b, int &x, int &y) {
if(!b) {
x = , y = ;
return a;
} else {
int tmp = exgcd(b, a%b, y, x);
y -= (a/b)*x;
return tmp;
}
}
void powmod(Matrix x, LL n, Matrix &res, int mod) {
res = E0;
while(n) {
if(n&) maMul(res, x, res, mod);
maMul(x, x, x, mod);
n >>= ;
}
}
int solve() { solver.getFail();
int mul = , res = ; for(int i = ; i < ; i++) mul *= M[i];
for(int i = ; i < ; i++) {
a[i] = mul/M[i];
Matrix tmp1, tmp2;
tmp1 = tmp2 = E0;
LL lv = L%M[i];
for(int k = M[i]; k >= ; k--) {
solver.getMat(k, M[i]);
maMul(tmp1, xx[k], tmp1, M[i]);
if(k <= lv)
maMul(tmp2, xx[k], tmp2, M[i]);
}
powmod(tmp1, L/M[i], tmp1, M[i]);
maMul(tmp2, tmp1, tmp1, M[i]);
ans[i] = ;
for(int k = ; k < sz; k++) {
ans[i] += tmp1.a[k][];
if(ans[i] >= M[i]) ans[i] -= M[i];
}
int xx, yy;
exgcd(a[i], M[i], xx, yy);
res += a[i]*ans[i]%mul*(xx%M[i])%mul;
if(res >= mul)
res -= mul;
}
return (res+mul)%mul;
}
int main() { getPrime();
int kase = ; for(int i = ; i < ; i++) for(int j = ; j < ; j++) E0.a[i][j] = i == j; while(scanf("%d%I64d", &N, &L) == ) {
solver.init();
for(int i = ; i <= N; i++) {
char s[];
scanf("%s", s);
solver.insert(s, i);
}
// printf("%d\n", sz);
printf("Case #%d: %d\n", ++kase, solve());
}
return ;
}

hdu 4878 ZCC loves words AC自动机+中国剩余定理+快速幂的更多相关文章

  1. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  2. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  3. Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂)

    Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂) 题目链接 题解: 多串匹配问题,很容易想到是AC自动机 先构建忌讳词语的AC自动机,构建时顺便记录一下这个点以及它的所有后 ...

  4. [poj2778 DNA Sequence]AC自动机,矩阵快速幂

    题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立ac自动机,考虑 ...

  5. BZOJ2553 Beijing2011禁忌(AC自动机+动态规划+矩阵快速幂+概率期望)

    考虑对一个串如何分割能取得最大值.那么这是一个经典的线段覆盖问题,显然每次取右端点尽量靠前的串.于是可以把串放在AC自动机上跑,找到一个合法串后就记录并跳到根. 然后考虑dp.设f[i][j]表示前i ...

  6. BZOJ1951 [Sdoi2010]古代猪文 中国剩余定理 快速幂 数论

    原文链接http://www.cnblogs.com/zhouzhendong/p/8109156.html 题目传送门 - BZOJ1951 题意概括 求 GM mod 999911659 M=∑i ...

  7. HDU 4876 ZCC loves cards(暴力剪枝)

    HDU 4876 ZCC loves cards 题目链接 题意:给定一些卡片,每一个卡片上有数字,如今选k个卡片,绕成一个环,每次能够再这个环上连续选1 - k张卡片,得到他们的异或和的数,给定一个 ...

  8. hdu 4873 ZCC Loves Intersection(大数+概率)

    pid=4873" target="_blank" style="">题目链接:hdu 4873 ZCC Loves Intersection ...

  9. hdu 4876 ZCC loves cards(暴力)

    题目链接:hdu 4876 ZCC loves cards 题目大意:给出n,k,l,表示有n张牌,每张牌有值.选取当中k张排列成圈,然后在该圈上进行游戏,每次选取m(1≤m≤k)张连续的牌,取牌上值 ...

随机推荐

  1. scala学习笔记:控制抽象

    def repeat(n:Int)(action: =>Unit)=for(i<-1 to n)action var i = 0 repeat(5){ println(i=i+1) } 另 ...

  2. asp中的几个取整函数fix(),int(),round()的用法

    asp中的几个取整函数是:fix(),int(),round(); Int(number).Fix(number)函数返回数字的整数部分.number 参数可以是任意有效的数值表达式.如果 numbe ...

  3. hdoj1584 蜘蛛牌 (区间型动态规划)

    hdoj1584 分析: f[i][j] 表示 把一串牌 牌 i 到 j 摞为一摞时 所花费最少的步数. d[i][j] 表示把牌 i 挪到牌 j 上时需要走的步数(最初给的状态). 以一串牌 3~8 ...

  4. SecureCRT 7 注册码

    Name: Sherrill Ray Company:  空 Serial Number:03-40-084141 License Key: ABWGUE ZPPZ6X XHTN2S 1N7PER A ...

  5. 捕获JSON 解析错误

    $json = <<<JSON { "origin":"Delhi", "destination":"Londo ...

  6. (转)MySQL Workbench的使用教程 (初级入门版)

    转自:http://www.cnblogs.com/yqskj/archive/2013/03/01/2938027.html MySQL Workbench 是 MySQL AB 最近释放的可视数据 ...

  7. 九度OJ 1163 素数

    题目地址:http://ac.jobdu.com/problem.php?pid=1163 题目描述: 输入一个整数n(2<=n<=10000),要求输出所有从1到这个整数之间(不包括1和 ...

  8. Integer ,==,int 的使用

    面试比较常见的题目:自己也经常忘记,所以就记下来了 上代码: Integer a = ,b=; Integer c = ,d=; System.out.println(a==b); System.ou ...

  9. 最近用到的Linux常用命令总结

    最近用到的Linux常用命令总结 - ls :显示当前目录文件信息 `ls -a -l` - cd :目录跳转 cd .. 上级目录 cd ~ home目录 cd - 最近目录 - cat :在屏幕上 ...

  10. redis 常用操作命令

    操作相关的命令连接 quit:关闭连接(connection)auth:简单密码认证 持久化 save:将数据同步保存到磁盘bgsave:将数据异步保存到磁盘lastsave:返回上次成功将数据保存到 ...