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 < ...
随机推荐
- 通信服务器哈希Socket查找(Delphi)
在Socket通信服务器的开发中,我们经常会需要Socket与某个结构体指针进行绑定.当连接量很大时,意味着需要个高效的查找方法 Delphi中提供了哈希算法类,以此类为基础,修改出Socket专用M ...
- 1014-32-首页13-cell的结构分析---导航栏中间title位置的按钮的尺寸设置---setFrame----
#import "HWTitleButton.h" #define HWMargin 5 @implementation HWTitleButton - (id)initWithF ...
- YCM的使用
YCM大概用来做3件事: (1)自动补全 (2)检查语法 (3)跳转到函数定义 然后涉及到两个关键的文件.vimrc 和 .ycm_extra_conf.py 首先需要正确的配置,在.vimrc中写入 ...
- wlr设置 Blog Ping
ref:http://www.cnblogs.com/zhangyang/archive/2011/07/22/2113856.html 设置 Blog Ping 1.什么是Ping服务(Ping S ...
- java.lang.NoSuchMethodError: cn.makangning.test.dao.Users.getUserBirthday()Ljava/sql/Date;
有时候出现这种怪异的问题,是由于多个版本的class存在. 比如说:某个java编译成class后,放到classes下面,然后lib目录下,也有这个class所在的jar包,这样就导致classpa ...
- python Beautiful Soup库入门
bs4库的HTML内容遍历方法 基于bs4库的HTML格式输出 显示:友好的显示 <tag>.prettify() 编码:bs4库将任何HTML输入都变成utf-8编码(python 3. ...
- 20145202马超 《Java程序设计》 实验一 实验报告
一.实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 二.实验内容 1.完成在Windows环境下对IDEA的配置: 2.实现求正整 ...
- 线程间通信(等待,唤醒)&Java中sleep()和wait()比较
1.什么是线程间通信? 多个线程在处理同一资源,但是任务却不同. 生活中栗子:有一堆煤,有2辆车往里面送煤,有2辆车往外拉煤,这个煤就是同一资源,送煤和拉煤就是任务不同. 2.等待/唤醒机制. 涉及的 ...
- 《Cracking the Coding Interview》——第5章:位操作——题目3
2014-03-19 05:57 题目:给定一个整数N,求出比N大,而且二进制表示中和N有相同个数的‘1’的最小的数,比如3是‘11’,接下来的5是‘101’,再接下来的6是‘110’. 解法:从低位 ...
- 【Linear Models for Binary Classification】林轩田机器学习基石
首先回顾了几个Linear Model的共性:都是算出来一个score,然后做某种变化处理. 既然Linear Model有各种好处(训练时间,公式简单),那如何把Linear Regression给 ...