矩阵快速幂

来源:互联网 发布:java遍历hashmap 编辑:程序博客网 时间:2024/05/20 16:10
Training little cats
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 9785 Accepted: 2340

Description

Facer's pet cat just gave birth to a brood of little cats. Having considered the health of those lovely cats, Facer decides to make the cats to do some exercises. Facer has well designed a set of moves for his cats. He is now asking you to supervise the cats to do his exercises. Facer's great exercise for cats contains three different moves:
g i : Let the ith cat take a peanut.
e i : Let the ith cat eat all peanuts it have.
s i j : Let the ith cat and jth cat exchange their peanuts.
All the cats perform a sequence of these moves and must repeat it m times! Poor cats! Only Facer can come up with such embarrassing idea. 
You have to determine the final number of peanuts each cat have, and directly give them the exact quantity in order to save them.

Input

The input file consists of multiple test cases, ending with three zeroes "0 0 0". For each test case, three integers nm and k are given firstly, where n is the number of cats and k is the length of the move sequence. The following k lines describe the sequence.
(m≤1,000,000,000, n≤100, k≤100)

Output

For each test case, output n numbers in a single line, representing the numbers of peanuts the cats have.

Sample Input

3 1 6g 1g 2g 2s 1 2g 3e 20 0 0

Sample Output

2 0 1

Source

PKU Campus 2009 (POJ Monthly Contest – 2009.05.17), Facer

矩阵快速幂模板,用到矩阵的一些性质

 1) ABC = A(BC),所以对矩阵处理时,只需要对之后的m个矩阵处理即可,最后乘的一个向量矩阵其实就是获取最后一行的n-1个元素,所以可以忽略,最后用一个循环来处理最后一行即可;

2)在对矩阵进进行变幻时,因为我们假设一个向量矩阵(x,y,  z),为我们所需要的结果,在处理交换和消0时,对单位矩阵的处理时非常简单的,但是在对加法处理时,会出现在对角线p[n][n]的时候多加一,累加的时候会出错,所以我们需要将矩阵的大小扩展1,这样对矩阵处理时,就不影响x,y,z的变值。

3)高速幂的剪枝:一般我们用二分法进行剪枝时处理出现像矩阵这种特殊的数据结构时,可以在两个矩阵相乘时,看看是不是稀疏矩阵,如果是稀疏或者可能是稀疏矩阵的话,可以改变矩阵相乘的顺序,我举个例子,或许很容易就明白:

1 2 3      1 2 3         1*1  1*2  1*3

4 5 6 *   4 5 6    =  4*1  4*2  4*3

67 8        6 7 8        6*1 6*2   6*3 ,相乘时,不是一次相加,而是分别相加,红色的想象成队列,然后里面有一串相加的数,每一行的每个数都进行相应的操作 分别加到每一列,这样只要前一个矩阵的数是0,那么这个数对应的列在当前情况下的一个加数为0,不考虑。

其实上面是对模板的解释,因为这就是个很普通的模板题。

代码:

#include<stdio.h>#include<string.h>int n;struct cat{__int64 v[110][110];cat(){memset(v,0,sizeof(v));}};cat Mul_M_M(cat p,cat q){cat t;for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)if(p.v[i][j])for(int k=0;k<=n;k++)t.v[i][k]+=p.v[i][j]*q.v[j][k];return t;}void Mul_MM(cat p,int x){cat t;for(int i=0;i<=n;i++)t.v[i][i] = 1;while(x){if(x&1){t = Mul_M_M(t,p);}p = Mul_M_M(p,p);x>>=1;}for(int i=0;i<n-1;i++)printf("%I64d ",t.v[n][i]);printf("%I64d\n",t.v[n][n-1]);}int main(){int m,k;char a[2];int d,c;while(scanf("%d%d%d",&n,&m,&k),n||m||k){cat p;for(int i=0;i<=n;i++)p.v[i][i] = 1;for(int i=0;i<k;i++){scanf("%s",a);switch(a[0]){case 'g':scanf("%d",&d);p.v[n][d-1]++;break;//加一;case 'e':scanf("%d",&d);for(int j=0;j<=n;j++)p.v[j][d-1] = 0;//qing0break;case 's':scanf("%d%d",&c,&d);for(int j=0;j<=n;j++){int t  = p.v[j][c-1];p.v[j][c-1] = p.v[j][d-1];p.v[j][d-1] = t;}//jiaohuan break; }}Mul_MM(p,m);}}


4 0
原创粉丝点击