bzoj 4000 矩阵快速幂优化DP

建立矩阵,跑快速幂

 1 /**************************************************************
 2     Problem: 4000
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:32 ms
 7     Memory:836 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cstring>
12 #define M 6
13
14 struct Matrix {
15     unsigned v[1<<M][1<<M];
16     const unsigned *operator[]( int i ) const { return v[i]; }
17 };
18
19 int n, m, p, k, bound;
20 int attack[3];
21 int stat[1<<M], id[1<<M], stot;
22 Matrix base, dest;
23
24 void make_unit( Matrix &x ) {
25     for( int i=0; i<stot; i++ )
26         for( int j=0; j<stot; j++ )
27             x.v[i][j] = i==j;
28 }
29 Matrix operator*( const Matrix &a, const Matrix &b ) {
30     Matrix c;
31     for( int i=0; i<stot; i++ )
32         for( int j=0; j<stot; j++ ) {
33             c.v[i][j] = 0;
34             for( int k=0; k<stot; k++ )
35                 c.v[i][j] += a[i][k]*b[k][j];
36         }
37     return c;
38 }
39 Matrix mpow( Matrix a, int b ) {
40     Matrix rt;
41     for( make_unit(rt); b; b>>=1,a=a*a )
42         if( b&1 ) rt=rt*a;
43     return rt;
44 }
45 int getarea( int s, int a ) {
46     int rt = 0;
47     for( int b=0; b<m; b++ ) {
48         if( (s>>b)&1 ) {
49             int aa = a;
50             if( b<k )
51                 aa >>= k-b;
52             else
53                 aa <<= b-k;
54             aa &= bound;
55             rt |= aa;
56         }
57     }
58     return rt;
59 }
60 void build() {
61     stot = 0;
62     memset( id, -1, sizeof(id) );
63     for( int s=0; s<=bound; s++ ) {
64         if( getarea(s,attack[1])&s ) continue;
65         stat[stot]=s;
66         id[s] = stot;
67         stot++;
68     }
69     for( int s1=0; s1<=bound; s1++ ) {
70         if( id[s1]==-1 ) continue;
71         for( int s2=0; s2<=bound; s2++ ) {
72             if( id[s2]==-1 ) continue;
73             if( getarea(s1,attack[2])&s2 ) continue;
74             if( getarea(s2,attack[0])&s1 ) continue;
75             base.v[id[s1]][id[s2]] = 1;
76         }
77     }
78 }
79 int main() {
80     scanf( "%d%d%d%d", &n, &m, &p, &k );
81     bound = (1<<m)-1;
82     for( int i=0; i<3; i++ )
83         for( int j=0,o; j<p; j++ ) {
84             scanf( "%d", &o );
85             attack[i] = attack[i] | (o<<j);
86         }
87     attack[1] ^= 1<<k;
88     build();
89     dest = mpow( base, n-1 );
90     unsigned ans = 0;
91     for( int i=0; i<stot; i++ )
92         for( int j=0; j<stot; j++ )
93             ans += dest[i][j];
94     printf( "%u\n", ans );
95 }

时间: 2024-08-22 08:23:26

bzoj 4000 矩阵快速幂优化DP的相关文章

矩阵快速幂 优化dp 模板

相关博客 :https://blog.csdn.net/china_xyc/article/details/89819376#commentBox 关于能用矩阵乘法优化的DP题目,有如下几个要求: 转移式只有加法,清零,减法etc.,max和min运算不允许 转移式中关于前几位dp结果得到的系数必须是常量 转移次数一般超级多 由于转移次数多,一般都要模一个int范围内的数 综上,举一个例子: dp[i]=a×dp[i−1]+b×dp[i−2]+c×dp[i−3] 其中,a,b,c是常量,而在需要

排队 矩阵快速幂优化dp

\(T1\) 排队 ? Description ?? 抢饭是高中生活的一部分,现在有一列队伍长度为 \(n\),(注意:由于人与人之间要保持距离,且不同情况所保持的距离大小不同,所以长度并不能直接体现队列的人数).已知男男之间的距离为 \(a\),男女之间距离为 bb,女女之间距离为 \(c\).一个男生打饭时间为 \(d\),一个女生打饭时间为 \(e\),求所有情况的排队时间总和(忽略身体的大小对队伍长度的贡献),答案对 $10^{9}+7 $取模. ?? Input Format 一行六个

LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)

哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \frac{1}{sum+1}*(f(i+1,s')+[s==s'])$ 状态数只有$C_{8+3}^3=165$个,所以就可以矩乘优化啦.再加上一个用于转移的$1$,矩阵大小是$166*166$的,因为多组询问,所以可以先把$2$的所有次幂的矩阵都预处理出来. 然后会发现复杂度是$O(T*166^3

czy的后宫——矩阵快速幂优化DP

题意 有 n 个位置排成一行,可以放 m 种妹子.每个位置可以放也可以不放,规定某些妹子不能相邻,求方案数. 分析 #include<bits/stdc++.h> using namespace std; typedef long long ll; ll qmul(ll x,ll y,ll p){ //快速乘 x%=p; y%=p; ll ans=0; while(y){ if(y&1){ ans+=x; if(ans>=p) ans-=p; //这样写不能有负数 } x<

hdu 5411 CRB and Puzzle (矩阵快速幂优化dp)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5411 题意:按题目转化的意思是,给定N和M,再给出一些边(u,v)表示u和v是连通的,问走0,1,2.....M步的方案数. 分析:这题和 hdu5318 The Goddess Of The Moon差不多,就是多了一个等比数列求和. 代码: #include <cstdio> #include <iostream> #include <cstring> using name

poj 3744 概率dp 矩阵快速幂优化

一位童子兵要穿过一条路,路上有些地方放着地雷.这位童子兵非常好玩,走路一蹦一跳的.每次他在 i 位置有 p 的概率走一步到 i+1 ,或者 (1-p) 的概率跳一步到 i+2.童子兵初始在1位置,求他安全通过这条道路的概率. 以所在位置为状态,dp[i] 表示在位置 i 的安全的概率. dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; // i 位置没有地雷 但是题目数据的范围是 10^8 这样dp的话会 TLE. 想想可以用矩阵快速幂优化.简单退出矩阵是 |p

HDU 5863 cjj&#39;s string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但是 m 很小的时候 发现此题DP并不合适.于是想可能是某种组合数学的问题可以直接公式算 看到题解的我.恍然大悟.对于这种数据.可以考虑一下矩阵快速幂优化的DP 首先要想到线性递推的 DP 式子 最直观的想法就是 dp[i][j] = 到第 i 个位置为止.前面最长匹配长度为 j 的方案数 但是如果仔

矩阵快速幂优化递推总结

RT,主要总结一下矩阵的求法. 首先能用矩阵快速幂优化的递推类型是f[n]=5f[n-3]+6f[n-2]+2f[n-1]+n^2+n+8之类的 也就是说递推是线性递推且f[n-i]前面的系数是常数,可以含有与n有关的多项式,也可以含有常数的这种递推,下面总结一下矩阵的写法: 先考虑最简单的常数,我们其实可以忽略常数,因为顶多在没有常数的矩阵外面加一行一列就行了 以f[n]=2f[n-1]+6f[n-2]+5f[n-3]+n^2+n为例 先写迭代的矩阵,一般可以写成一行,右边有几项写几项 {f[

poj3744之矩阵快速幂+概率DP

Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4410   Accepted: 1151 Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties,