文泽想在埃及做案n次,并且想在最后不用得到惩罚。案件的被分成几种类型。比如说,案件A,当案件A被重复犯两次时,案件A将被认为不是犯罪案件,因此犯案人不用得到惩罚。也就是说,案件A被犯偶数次时,犯案人将不用得到惩罚。又比如案件B,当案件B被犯的次数是5的倍数时,犯案人将不用得到惩罚。

更具体的说,现在知道有c组条件。每组条件包含的信息如下:

1.  案件类型 ti ,

2.  底数 mi ,表示该类型案件重复n* mi (n是非负整数)次时,犯案人可以不用得到惩罚。

对于同一种案件,他的条件可能会被列出多个,在这种情况下,犯案人对该种案件犯罪次数至少满足其中一个条件就可以不受到惩罚。

文泽想要知道他犯n次罪后,并且不得到惩罚的犯罪情况的种数。

不得到惩罚的条件是,对于所有犯过n个案件的所有案件类型中,每种类型的案件都不用得到惩罚。

每个案件的犯罪顺序是有意义的。说明一下,现在有两种犯罪的案件序列W1和W2,如果对于所有的i(1≤i≤n)使得 W1i=W2i ,我们就认为这两个案件序列是一样的。

样例解释:

在样例中,有16种情况,分别为: AAAAA, AAABB, AABAB, AABBA, ABAAB, ABABA, ABBAA, BAAAB, BAABA, BABAA, BBAAA, ABBBB, BABBB, BBABB, BBBAB, BBBBA.

Input
单组测试数据
第一行包含两个整数,n和c(0≤n≤10^18,0≤c≤1000),
分别表示文泽想要犯罪案件的个数和避免被惩罚的条件的组数。 接下来有c行。每行表示一组条件。
每组条件包含案件类型ti,和底数mi
这里ti一共有26种案件类型,分别用26个大写字母表示。
每个底数mi是一个正整数,所有mi的乘积不会超过123。
有些条件可能被重复列出多次。 如果某些案件类型没有在条件中被列出,那么文泽将不会考虑去犯这些类型的案件。
Output
共一行,表示文泽犯n次罪后,并且不得到惩罚的犯罪情况的种数对12345取余。
Input示例
5 2
A 1
B 2
Output示例
16
(吐槽 对于一个刚开始学矩乘的人来说 这种题还是有点困难 存着以后加深理解
————————————————————————————————
这道题呢 因为所有mi的乘积不会超过123 所以本质不同的状态(S)只有<=123种
因为 对于每个有限制条件的字符,只需记录(它的出现次数)%(限制条件的mi之积)
枚举n以及状态 可以做到n*123^2吧
那就可以矩阵乘法做到123^3logn了(ccz原话
类似(f[i][S]表示考虑前i个字符,字符出现情况是S的方案数)
因为状态很少 我们可以预处理状态 然后离散化成整数
我直接用vector表示26维的状态 然后在离散化(利用map)
S有26维,dfs求出所有S,每个S直接用一个大小26的vector存,放进map离散化,枚举转移就行辣
具体不好讲 看看代码吧QAQ 不懂可以私我(我尽力
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define LL long long
using namespace std;
const int mod=;
LL read(){
LL ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
LL mx=,n,m;
char ch[];
int k,vis[],ed[][],h[][];
int b[][],c[][],d[][];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
vector<int>v1();
map<vector<int>,int>mmp;
int cnt;
void dfs(int k){
if(k==){mmp[v1]=cnt++; return;}
if(vis[k])for(int i=;i<vis[k];i++){v1[k]=i; dfs(k+);}
else{v1[k]=; dfs(k+);}
}
void pmod(int b[][],int c[][]){
for(int i=;i<mx;i++)
for(int j=;j<mx;j++) d[i][j]=;
for(int i=;i<mx;i++)
for(int k=;k<mx;k++)
for(int j=;j<mx;j++) (d[i][j]+=b[i][k]*c[k][j])%=mod;
for(int i=;i<mx;i++)
for(int j=;j<mx;j++) b[i][j]=d[i][j];
}
int main()
{
n=read(); m=read();
for(int i=;i<m;i++){
scanf("%s",ch); k=read();
vis[ch[]-'A']=;
ed[ch[]-'A'][k]=;
}
for(int i=;i<;i++) if(vis[i]){
for(int j=;j<;j++) if(ed[i][j]) vis[i]=lcm(vis[i],j);
mx*=vis[i];
for(int j=;j<;j++) if(ed[i][j]){
for(int k=;k<vis[i];k+=j) h[i][k]=;//左闭右开
}
}
dfs();//预处理出所有状态 map离散化
int v2;
for(map<vector<int>,int>::iterator it=mmp.begin();it!=mmp.end();it++){//处理状态之间的转移
v1=it->first; v2=it->second;
for(int i=;i<;++i)if(vis[i]){
v1[i]=(v1[i]+)%vis[i];
++c[mmp[v1]][v2];
v1[i]=(v1[i]-+vis[i])%vis[i];
}
}
for(int i=;i<mx;i++) b[i][i]=;
for(;n;n>>=,pmod(c,c)) if(n&) pmod(b,c);
int ans=;
for(map<vector<int>,int>::iterator it=mmp.begin();it!=mmp.end();it++){//枚举状态是否合法
bool f=false;
v1=it->first; v2=it->second;
for(int i=;i<;i++) if(vis[i]&&!h[i][v1[i]]) f=true;
if(!f) ans=(ans+b[v2][])%mod;
}
printf("%d\n",ans);
return ;
}
 

51nod 1583 犯罪计划——矩阵乘法优化dp的更多相关文章

  1. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

  2. 斐波那契数列 矩阵乘法优化DP

    斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007​\),\(n\le 10^{18}​\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...

  3. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  4. 矩阵乘法优化DP复习

    前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...

  5. 矩阵乘法优化DP

    本文讲一下一些基本的矩阵优化DP的方法技巧. 定义三个矩阵A,B,C,其中行和列分别为$m\times n,n \times p,m\times p$,(其中行是从上往下数的,列是从左往右数的) $C ...

  6. 【bzoj2476】战场的数目 矩阵乘法优化dp

    题目描述 (战场定义为对于最高的一列向两边都严格不增的“用积木搭成”的图形) 输入 输入文件最多包含25组测试数据,每个数据仅包含一行,有一个整数p(1<=p<=109),表示战场的图形周 ...

  7. 【矩阵乘法优化dp】[Codeforces 621E] Wet Shark and Blocks

    http://codeforces.com/problemset/problem/621/E E. Wet Shark and Blocks time limit per test 2 seconds ...

  8. luoguP2768: 珍珠项链(矩阵乘法优化DP)

    题意:有K种珍珠,每种N颗,求长度为1~N的项链,包含K种珍珠的项链种类数.N<=1e9, K<=30; 思路:矩阵快速幂,加个1累加前缀和即可. #include<bits/std ...

  9. bzoj 4870: [Shoi2017]组合数问题 [矩阵乘法优化dp]

    4870: [Shoi2017]组合数问题 题意:求 \[ \sum_{i=0}^{n-1} \binom{nk}{ik+r} \mod p \] \(n \le 10^9, 0\le r < ...

随机推荐

  1. 在Ubuntu下安装gcc编译器+测试

    1.输入命令: sudo apt-get install gcc libc6-dev 2.创建文件hello.c使用命令: touch hello.c 3.在hello.c中写入:  #include ...

  2. MySQL Group Replication数据安全性保障

    本文来自数据库内核专栏 在之前的文章中,介绍了MGR对数据可靠性.可用性和一致性的实现方案.简单来说,MGR通过基于paxos协议的多副本来实现数据的可靠性,通过多副本上的majority机制来实现可 ...

  3. USACO Section1.2 Dual Palindromes 解题报告

    dualpal解题报告 —— icedream61 博客园(转载请注明出处)-------------------------------------------------------------- ...

  4. Java线程的两种实现形式

    一.创建线程的第一种方式:继承Thread类 class Demo extends Thread{ @Override public void run() { super.run(); for(int ...

  5. web自动化测试,定位不到元素的原因及解决方案(持续更新中2018年9月29日)

    主要讲自己在实战中遇到的坑: 1.动态id定位不到元素 分析原因:每次打开页面,ID都会变化.用ID去找元素,每次刷新页面ID都会发生变化. 解决方案:推荐使用xpath的相对路径方法或者cssSel ...

  6. 你的第一个自动化测试:Appium 自动化测试

    前言: 这是让你掌握 App 自动化的文章 一.前期准备 本文版权归作者和博客园共有,原创作者:http://www.cnblogs.com/BenLam,未经作者同意必须在文章页面给出原文连接. 1 ...

  7. linux->centos7设置tomcat开机自启

    找到/etc/rc.d/文件下的rc.local,添加如下内容 export JAVA_HOME=/usr/local/jdk1.8.0_144export JRE_HOME=$JAVA_HOME/j ...

  8. [转]个人对AutoResetEvent和ManualResetEvent的理解

    仅个人见解,不对之处请指正,谢谢. 一.作用 AutoResetEvent和ManualResetEvent可用于控制线程暂停或继续,拥有重要的三个方法:WaitOne.Set和Reset. 这三个方 ...

  9. unity值得推荐的网址

    免费字体下载网站:http://www.dafont.com/ 免费声音文件下载网站:http://freesound.org/          http://incompetech.com/mus ...

  10. Linux(Ubuntu 命令大全)

    Ubuntu 一. Ubuntu简介 Ubuntu(乌班图)是一个基于Debian的以桌面应用为主的Linux操作系统,据说其名称来自非洲南部祖鲁语或科萨语的“ubuntu”一词,意思是“人性”.“我 ...