POJ3735

题目链接:http://poj.org/problem?id=3735

解题思路:

  先构造一个(n+1)*(n+1)的单位矩阵E,在此基础上进行操作:

  1、g i     ------------->      E[0][i] ++;

  2、s i j   ------------->  for(int k=0;k<=n;k++)  swap(E[k][i],E[k][j]);

  3、e i    ------------->  for(int k=0;k<=n;k++) E[k][i]=0;

  上面的这一个部分本来我是构造多个单位矩阵,在单位矩阵上进行操作的,操作后的矩阵相乘的结果就是总的操作,结果就是一个TLE。。。后来改成这样才AC了。

  然后再构造一个矩阵A,A只有左上角为1,其他的都为0。操作m次,其实就是A*(E^m)。矩阵快速幂,上!

AC代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=110;
 8 struct Matrix{
 9     ll mat[maxn][maxn];
10 };
11 Matrix Multiply(Matrix x,Matrix y,int n){
12     Matrix temp;
13     for(int i=0;i<=n;i++){
14         for(int j=0;j<=n;j++){
15             temp.mat[i][j]=0;
16             for(int k=0;k<=n;k++){
17                 if(x.mat[i][k]&&y.mat[k][j])    //没有这个优化TLE
18                     temp.mat[i][j]+=(x.mat[i][k]*y.mat[k][j]);
19             }
20         }
21     }
22     return temp;
23 }
24 Matrix Fast_Power(Matrix a,int m,int n){
25     Matrix res;
26     for(int i=0;i<=n;i++){
27         for(int j=i;j<=n;j++){
28             if(i==j)    res.mat[i][j]=1;
29             else    res.mat[i][j]=res.mat[j][i]=0;
30         }
31     }
32     while(m){
33         if(m&1) res=Multiply(res,a,n);
34         m>>=1;
35         a=Multiply(a,a,n);
36     }
37     return res;
38 }
39 
40 int main(){
41     Matrix rt;
42     int n,m,k,a,b;
43     char t[3];
44     while(scanf("%d%d%d",&n,&m,&k)==3&&(n||m||k)){
45         for(int i=0;i<=n;i++){
46             for(int j=i;j<=n;j++){
47                 if(i==j)    rt.mat[i][j]=1;
48                 else    rt.mat[i][j]=rt.mat[j][i]=0;
49             }
50         }//构造出一个(n+1)*(n+1)的单位矩阵
51         while(k--){
52             scanf("%s",t);
53             if(t[0]=='g'){
54                 scanf("%d",&a);
55                 rt.mat[0][a]++;
56             }
57             else if(t[0]=='e'){
58                 scanf("%d",&a);
59                 for(int i=0;i<=n;i++)
60                     rt.mat[i][a]=0;
61             }
62             else{
63                 scanf("%d %d",&a,&b);
64                 for(int i=0;i<=n;i++){
65                     if(rt.mat[i][a]||rt.mat[i][b])
66                         swap(rt.mat[i][a],rt.mat[i][b]);
67                 }
68             }
69         }
70         if(m==0){
71             for(int i=0;i<n;i++){
72                 if(i!=0)    printf(" ");
73                 printf("0");
74             }
75         }
76         else{
77             Matrix t;
78             memset(t.mat,0,sizeof(t));
79             t.mat[0][0]=1;
80             Matrix ret=Multiply(t,Fast_Power(rt,m,n),n);
81             for(int i=1;i<=n;i++){
82                 if(i!=1)    printf(" ");
83                 printf("%lld",ret.mat[0][i]);
84             }
85         }
86         printf("\n");
87     }
88     return 0;
89 }

 

转载于:https://www.cnblogs.com/Blogggggg/p/7425896.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值