51nod 1583 犯罪计划——矩阵乘法优化dp
文泽想在埃及做案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.
单组测试数据
第一行包含两个整数,n和c(0≤n≤10^18,0≤c≤1000),
分别表示文泽想要犯罪案件的个数和避免被惩罚的条件的组数。 接下来有c行。每行表示一组条件。
每组条件包含案件类型ti,和底数mi
这里ti一共有26种案件类型,分别用26个大写字母表示。
每个底数mi是一个正整数,所有mi的乘积不会超过123。
有些条件可能被重复列出多次。 如果某些案件类型没有在条件中被列出,那么文泽将不会考虑去犯这些类型的案件。
共一行,表示文泽犯n次罪后,并且不得到惩罚的犯罪情况的种数对12345取余。
5 2
A 1
B 2
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的更多相关文章
- 形态形成场(矩阵乘法优化dp)
形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...
- 斐波那契数列 矩阵乘法优化DP
斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007\),\(n\le 10^{18}\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
- 矩阵乘法优化DP复习
前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...
- 矩阵乘法优化DP
本文讲一下一些基本的矩阵优化DP的方法技巧. 定义三个矩阵A,B,C,其中行和列分别为$m\times n,n \times p,m\times p$,(其中行是从上往下数的,列是从左往右数的) $C ...
- 【bzoj2476】战场的数目 矩阵乘法优化dp
题目描述 (战场定义为对于最高的一列向两边都严格不增的“用积木搭成”的图形) 输入 输入文件最多包含25组测试数据,每个数据仅包含一行,有一个整数p(1<=p<=109),表示战场的图形周 ...
- 【矩阵乘法优化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 ...
- luoguP2768: 珍珠项链(矩阵乘法优化DP)
题意:有K种珍珠,每种N颗,求长度为1~N的项链,包含K种珍珠的项链种类数.N<=1e9, K<=30; 思路:矩阵快速幂,加个1累加前缀和即可. #include<bits/std ...
- bzoj 4870: [Shoi2017]组合数问题 [矩阵乘法优化dp]
4870: [Shoi2017]组合数问题 题意:求 \[ \sum_{i=0}^{n-1} \binom{nk}{ik+r} \mod p \] \(n \le 10^9, 0\le r < ...
随机推荐
- Pandas 基本技巧
1.数据查看和转置 import numpy as np import pandas as pd # 导入numpy.pandas模块 # 数据查看.转置 df = pd.DataFrame(np.r ...
- python——input()函数
在使用input()内置函数输入数字时,要注意一点: input()的返回值始终是字符串,所以type(number)永远是<class 'str'>! 如: >>> t ...
- Ubuntu 14.10 配置JDK + J2EE
本文仅作为本人在Ubuntu 14.10下安装JDK + J2EE的一个记录: 安装JDK 从Oracle的官网下载jdk-7u75-linux-x64.tar.gz 将jdk-7u75-linux- ...
- Android 游标
静下心来,学一下Android的数据库连接. 1.直接从getReadableDatabase()与getWritableDatabase()入手. --getReadableDatabase( ...
- cocos2d-x 3.0环境配置(转)
cocos2d-x 3.0发布有一段时间了,作为一个初学者,我一直觉得cocos2d-x很坑.每个比较大的版本变动,都会有不一样的项目创建方式,每次的跨度都挺大…… 但是凭心而论,3.0RC版本开始 ...
- 5.bootstrap栅格 清除浮动
只要用到栅格,就注意要清除浮动,清除方法就是在父元素的class上加一个clearfix 1.情景: . <div class="col-sm-7"> <div ...
- java前台传参json,后台用map或者实体对象接收
(一)前台传js对象,里面包含数组,后台用map接收 (1)第一种情况:数组里不包含js对象 var param ={}: param.id=id; param.name=name; var scor ...
- HTML5技巧
HTML5技巧 HTML5 技巧一:当今科技发展的速度真惊人,稍不留神,就可能无法跟上它的步伐.新一代的HTML-HTML5的发展也不停的带给我们新的惊喜,我们将通过这篇文章向大家介绍一些HTML ...
- QQ空间相册展示特效
<!doctype html> <html lang="en"> <head> <title>QQ空间相册展示特效<title ...
- 《Cracking the Coding Interview》——第13章:C和C++——题目4
2014-04-25 19:50 题目:深拷贝和浅拷贝有什么区别?如何应用? 解法:深拷贝传值,浅拷贝传引用.java里对此做了限制,而C++里面用起来更自由.大结构不宜传值,因为拷贝过程效率低. 代 ...