HDU 5411

题意:

Count the number of different patterns by counting the number of different paths of length at most m-1.

思路:

其实这类问题就是求:
S=I+A+A2+...+AmS=I+A+A^2+...+A^m
一般普适的计算方式是:

(AmS)=(AI0I)m∗(I0)

\left( \begin{array}{ccc} A^m\\ S\\ \end{array} \right) =\left( \begin{array}{ccc} A & 0\\ I & I\\ \end{array} \right)^m * \left( \begin{array}{ccc} I\\ 0\\ \end{array} \right)
这样做的好处是可以得到最后的矩阵S,然后求S的所有元素和即是答案-1(没统计 ∅\emptyset),不过这题n <= 50 ,矩阵大小可能会超过100*100,时间复杂度将达到 O(N3logM)O(N^3\log M)再加上数据有20组,会被卡常数TLE,但有一个办法就是将矩阵乘法的取模操作从最内层移到第二层(因为mod只有2015,也就是说矩阵最大元素只有2014,最内层的乘法加法操作不会爆int),可以进行一定常数优化,,刚好可以卡着时间AC(大概480ms)

但是这题并不需要我们求出最后的加和矩阵S,仅需要它的各项元素和即可,那么我们可以把这个矩阵简化成这样(假设邻接是个四阶矩阵):

⎛⎝⎜⎜⎜⎜⎜⎜11A1100001⎞⎠⎟⎟⎟⎟⎟⎟m=⎛⎝⎜⎜⎜⎜⎜⎜a1a2Ama3a40000a5⎞⎠⎟⎟⎟⎟⎟⎟

\left( \begin{array}{ccc}&&& &0\\&&&& 0\\&&A& &0\\&&&& 0\\ 1& 1&1&1&1\\ \end{array} \right)^m= \left( \begin{array}{ccc}&&& &0\\&&&& 0\\&&A^m& &0\\&&&& 0\\ a_1& a_2&a_3&a_4&a_5\\ \end{array} \right)
ans=∑ni=1aians=\sum_{i=1}^na_i
这样做就避免了空间的浪费,且保留下来了答案,当然这里初始矩阵的最下面一行1也可以放去最上层,最左层,最右层,因为是计算 AkA^k所有元素和,并无影响。
这种做法复杂度与之前一致,但因为矩阵大小降了近乎一半,耗时相对少了很多(大概93msAC)

代码:

方法1:

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;const int maxn = 100 + 5 ;
const int mod = 2015 ;
struct Matrix {int n , m ;int a[maxn][maxn] ;Matrix( int n , int m ){this->n = n ;this->m = m ;cls(a) ;}Matrix operator * ( const Matrix &tmp ){Matrix res( n , tmp.m ) ;for( int i = 0 ; i < n ; i++ ){for( int j = 0 ; j < tmp.m ; j++ ){for( int k = 0 ; k < m ; k++ )res.a[i][j] += a[i][k] * tmp.a[k][j] ;if( res.a[i][j] > mod ) res.a[i][j] %= mod ;}}return res ;}
};void Matrix_print( Matrix x ){for( int i = 0 ; i < x.n ; i++ ){for( int j = 0 ; j < x.m ; j++ ){cout << x.a[i][j] << ' ';}cout << endl;}cout << endl ;
}
Matrix fast_pow( Matrix x , int n ){Matrix res( x.n , x.m ) ;for( int i = 0 ; i < x.n ; i++ ) res.a[i][i] = 1 ;while( n ){if( n & 1 )res = res * x ;n >>= 1 ;x = x * x ;}return res ;
}int main(){
//  freopen("input.txt","r",stdin);int t  ; cin >> t ;while( t-- ){int n , m ;cin >> n >> m ;Matrix G( 2 * n , 2 * n ) ;for( int i = 0 ; i < n ; i++ ){int k ;scanf( "%d" , &k ) ;for( int j = 0 ; j < k ; j++ ){int tmp ;scanf( "%d" , &tmp ) ;G.a[i][tmp-1] = 1 ;}}for( int i = n ; i < 2 * n ; i++ ){G.a[i][i - n] = 1 ;G.a[i][i] = 1 ;}Matrix base( 2 * n , n ) ;for( int i = 0 ; i < n ; i++ )base.a[i][i] = 1 ;G = fast_pow( G , m  );//Matrix_print( G ) ;base = G * base ;//Matrix_print( base ) ;int ans = 0 ;for( int i = n ; i < 2 * n ; i++ )for( int j = 0 ; j < n ; j++ )ans += base.a[i][j] ;cout << ( ans + 1 ) % mod << endl ;}return 0;
}

方法2:

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;const int maxn = 100 + 5 ;
const int mod = 2015 ;
struct Matrix {int n , m ;int a[maxn][maxn] ;Matrix( int n , int m ){this->n = n ;this->m = m ;cls(a) ;}Matrix operator * ( const Matrix &tmp ){Matrix res( n , tmp.m ) ;for( int i = 0 ; i < n ; i++ ){for( int j = 0 ; j < tmp.m ; j++ ){for( int k = 0 ; k < m ; k++ )res.a[i][j] += a[i][k] * tmp.a[k][j] ;if( res.a[i][j] > mod ) res.a[i][j] %= mod ;}}return res ;}
};void Matrix_print( Matrix x ){for( int i = 0 ; i < x.n ; i++ ){for( int j = 0 ; j < x.m ; j++ ){cout << x.a[i][j] << ' ';}cout << endl;}cout << endl ;
}
Matrix fast_pow( Matrix x , int n ){Matrix res( x.n , x.m ) ;for( int i = 0 ; i < x.n ; i++ ) res.a[i][i] = 1 ;while( n ){if( n & 1 )res = res * x ;n >>= 1 ;x = x * x ;}return res ;
}int main(){
//  freopen("input.txt","r",stdin);int t  ; cin >> t ;while( t-- ){int n , m ;cin >> n >> m ;Matrix G( n + 1 , n + 1 ) ;for( int i = 0 ; i < n ; i++ ) G.a[n][i] = 1 ;for( int i = 0 ; i < n ; i++ ){int k ;scanf( "%d" , &k ) ;for( int j = 0 ; j < k ; j++ ){int tmp ;scanf( "%d" , &tmp ) ;G.a[i][tmp-1] = 1 ;}}//Matrix_print( G ) ;G = fast_pow( G , m );//Matrix_print( G ) ;int ans = 0 ;for( int i = 0 ; i <= n ; i++ )ans += G.a[n][i] ;cout << ( ans ) % mod << endl ;}return 0;
}

HDU 5411 CRB and Puzzle(矩阵快速幂+可达矩阵)相关推荐

  1. hdu 5411 CRB and Puzzle(矩阵快速幂)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5411 解题思路: 题目大意: 给定n个点 常数m 下面n行第i行第一个数字表示i点的出边数,后面给出 ...

  2. HDU - 5411 CRB and Puzzle 矩阵快速幂

    HDU - 5411 考虑直接dp会T, 用矩阵优化一下就好了. #include<bits/stdc++.h> #define LL long long #define LD long ...

  3. hdu 5411 CRB and Puzzle 矩阵高速幂

    链接 题解链接:http://www.cygmasot.com/index.php/2015/08/20/hdu_5411/ 给定n个点 常数m 以下n行第i行第一个数字表示i点的出边数.后面给出这些 ...

  4. HDU 5411 CRB and Puzzle (2015年多校比赛第10场)

    1.题目描写叙述:点击打开链接 2.解题思路:本题实际是是已知一张无向图.问长度小于等于m的路径一共同拥有多少条. 能够通过建立转移矩阵利用矩阵高速幂解决.当中,转移矩阵就是输入时候的邻接矩阵,同一时 ...

  5. 【矩阵快速幂】 HDU 5411 CRB and Puzzle 等比

    点击打开链接 题意显然是 求 A+A^2+A^3+....+A^m 这就是经典题目 矩阵乘法十种经典题目 递归解决 后半部分提取 A^(m/2) 该题再特判下 m==1的时候 #include < ...

  6. hdu 5411 CRB and Puzzle

    Sample Input 1 3 2 1 2 1 3 0 Sample Output 6 Hint possible patterns are ∅, 1, 2, 3, 1→2, 2→3 解释样例: 第 ...

  7. HDU1757(矩阵快速幂+简单的矩阵构造)

    很简单的矩阵构造看似很麻烦,其实直接写就ok了. ⎡⎣⎢⎢⎢⎢f(n)f(n−1)....f(n−9)⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢a100....0b0100c0010d0000e0000f00 ...

  8. HDU - 5667 Sequence(矩阵快速幂+费马小定理降幂)

    题目链接:点击查看 题目大意:给出函数f(x): 现给出n,a,b,c,mod,求f(n)对mod取模后的结果 题目分析:这个题目相对于前几个题来说稍微加大了点难度,但还是挺水的一个题,首先我们可以对 ...

  9. 2021HDU多校8 - 7057 Buying Snacks(矩阵快速幂套NTT优化dp)

    题目链接:点击查看 题目大意:给出 nnn 种糖果,每种糖果有大小包装之分,有三种购买方案,价钱分别如下: 单独购买一个小的,花费一块钱 单独购买一个大的,花费两块钱 ∀i>1\forall i ...

  10. 矩阵快速幂及斐波那契数列模板

    本篇博客先给出矩阵快速幂以及利用矩阵快速幂求斐波那契数列的模板,讲解待更新-- const int N=10; int tmp[N][N]; void multi(int a[][N],int b[] ...

最新文章

  1. leetcode-55 跳跃游戏
  2. 微信小程序 UI 判断 循环
  3. 【CCF】201903-1小中大
  4. Jupyter notebook基础教程(启动,汉化,操作)
  5. pcie数据反_PCIe事务层の详解(一)
  6. Activiti CamelTask(骆驼任务)
  7. Spark编程基础(林子雨)第四章实验
  8. android远程桌面闪退,win7系统连接远程桌面出现闪退问题的两种解决方法详细教程...
  9. 手机端APP接口拦截(抓包)-Charles
  10. android自定义视频列表,Android列表视频播放开发之路
  11. 建筑力学与结构【5】
  12. Unity3d开发wp8问题汇总
  13. 如何判断一家软件公司是否靠谱
  14. 如何修改PDF文件,怎样将PDF文件拆分
  15. windows补丁修复
  16. Js word格式doc文件下载
  17. 北京大学C语言学习第三天
  18. ECharts动态图表展示
  19. linux学习lesson16
  20. 台湾印象: 太平洋的风

热门文章

  1. 数字电路 逻辑函数的化简之 公式化简法
  2. 航测无人机测绘地理信息免费资料
  3. 10款非常棒的开源论坛系统推荐
  4. 计算机科学与技术与数学建模,数学建模
  5. 教你3招解决PDF文字无法复制的所有问题!!!
  6. office一直提示配置进度与图标问题
  7. MacOS 64位GaussView5的破解
  8. 深度学习系列讲座:谷歌翻译核心技术 Seq2Seq
  9. TextView的属性
  10. PHP 生成 ppt,PHP生成PPT文件