文泽想在埃及做案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. linux 安装mysql5.6 yum

    安装mysql: 查看mysql: rpm -qa | grep -i mysql 安装必要的环境 yum -y install gcc gcc-c++ ncurses-devel perl 查看环境 ...

  2. php中==和===的含义及区别

    ===比较两个变量的值和类型:==比较两个变量的值,不比较数据类型. 比如 $a = '123'; $b = 123; $a === $b为假: $a == $b为真: 有些情况下不能使用==,可以使 ...

  3. C# 设定弹出窗体位置

    一.C#中弹出窗口位置 加入命名空间 using System.Drawing using System.Windows.Forms 假定窗口名为form1,则 //窗体位置在屏幕中间 form1.S ...

  4. B1016 部分A+B (15分)

    B1016 部分A+B (15分) 输入格式: 输入在一行中依次给出 A.DA.B.DB,中间以空格分隔,其中 \(0<A,B<10^10\). 输出格式: 在一行中输出 PA+PB的值. ...

  5. POJ:3185-The Water Bowls(枚举反转)

    The Water Bowls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7402 Accepted: 2927 Descr ...

  6. vue 组件间数据传递

    父组件向子组件传值 方法一: 子组件想要使用父组件的数据,需要通过子组件的 props 选项来获得父组件传过来的数据. 1.父组件parent.vue中代码: <template> < ...

  7. sublime text基本配置备份

    sublime text基本配置备份: // Settings in here override those in "Default/Preferences.sublime-settings ...

  8. Python 3基础教程1-环境安装和运行环境

    本系列开始介绍Python3的基础教程,为什么要选中Python 3呢?之前呢,学Python 2,看过笨方法学Python,学了不到一个礼拜,就开始用Python写Selenium脚本.最近看到一些 ...

  9. 【非原创】tomcat 安装时出现 Failed to install Tomcat7 service

    tomcat 安装时出现 Failed to install Tomcat7 service 今天在安装tomcat时提示 Failed to install Tomcat7 service了,花了大 ...

  10. 1086 Tree Traversals Again (25 分)(二叉树的遍历)

    用栈来模拟一棵二叉树的先序遍历和中序遍历过程,求这棵二叉树的后序遍历 由题棵知道:push是先序遍历 pop是中序遍历 #include<bits/stdc++.h> using name ...