zoukankan      html  css  js  c++  java
  • How many ways?? 矩阵

    分析

    这个题又是特殊的最短路问题
    等等再说矩阵的问题,因为这个题的范围比较小,所以。。。可以写一个计数DP来解决。
    估计看一眼代码就可以明白了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int N=1e2+10;
    int dis[N][N],to[N][N];
    int main(){
    	int n,m;
    	while(~scanf("%d%d",&n,&m)){
    		if(n==0&&m==0)return 0;
    		memset(to,0,sizeof(to));
    		for(int i=1;i<=m;i++){
    			int a,b;
    			scanf("%d%d",&a,&b);
    			to[a][b]=1;
    		}
    		int T;
    		scanf("%d",&T);
    		while(T--){
    			int a,b,k;
    			memset(dis,0,sizeof(dis));
    			scanf("%d%d%d",&a,&b,&k);
    			dis[0][a]=1;
    			for(int x=1;x<=k;x++){
    				for(int i=0;i<n;i++){
    					for(int j=0;j<n;j++){
    						if(to[i][j])
    							dis[x][j]=(dis[x][j]+dis[x-1][i])%1000;
    					}
    				}
    			}
    			printf("%d
    ",dis[k][b]);
    		}
    	}
    }
    

    因为时间复杂度的问题,所以这个跑起来比矩阵还要快。
    但是如果把(k)的范围调大而(n)的范围不变,这样就会T,(k)是想多大就多大的,因为点可以重复经过,所以这题又被数据坑了?
    矩阵的题也写过很多次了,敏感的话可以直接写出答案就是(A^k)这个矩阵中对应的点的值。
    可以这么考虑,如果有(dis[i][k]=a,dis[k][j]=b,i->k,k->j)均只走了一步,那么根据分步乘法,走两步时(dis[i][j]+=dis[i][k]×dis[k][j]),正好满足矩阵运算的规则。
    之前一直没有证明矩阵快速幂的正确性,要证明这个,只需要证明它满足结合律就行。

    首先我们证明 [公式]

    [公式][公式] 的矩阵, [公式] [公式]

    [公式]

    [公式]

    所以 [公式] ,即 [公式]

    现在进行归纳证明,假设在 [公式] 时对 [公式] 个矩阵相乘满足结合律,证明在 [公式] 时也满足结合律

    我们现在试图证明对任意顺序做乘法的 [公式] ,都与 [公式] 相等

    考虑任意顺序做乘法的矩阵,找到最后一次相乘的乘号(即没有被任何一个括号包含的乘号),考虑这个乘号两边的矩阵,不妨设左边共有 [公式] 个矩阵,右边共有 [公式] 个矩阵,那么由于 0"> ,所以 [公式] ,所以根据归纳假设,左边可以写成 [公式] ,右边可以写成 [公式]

    然后,因为我们知道了 [公式] 满足结合律,我们可以将 [公式] 写成 [公式] 的形式,然后一层一层将右侧的括号拆掉即可

    所以任意顺序相乘的 [公式] 都相等,等于 [公式]

    现在证明出了对于 [公式] 时结合律也成立,所以对任意 [公式][公式] 个矩阵相乘符合结合律。

    证毕。

    我相信现在你对矩阵快速幂已经熟能生巧了

  • 相关阅读:
    CSS:CSS 创建
    mfs-用户
    java实现扑克牌移动
    java实现扑克牌移动
    java实现扑克牌移动
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12906291.html
Copyright © 2011-2022 走看看