TsinsenA1221 大楼【矩阵快速幂】

题目分析:

重新定义矩阵运算,$*$等价于$+$,$+$等价于$max$。

然后倍增一下,再二分一下。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n;long long m;
 5 struct mat{long long arr[102][102];}G,mmp;
 6 mat hh[70];
 7 
 8 mat operator*(mat alpha,mat beta){
 9     int flag = 0;
10     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(alpha.arr[i][j]!=0)flag=1;
11     if(flag == 0) return beta;
12     memset(mmp.arr,0,sizeof(mmp.arr));
13     for(int k=1;k<=n;k++){
14     for(int i=1;i<=n;i++){
15         for(int j=1;j<=n;j++){
16         if(alpha.arr[i][k] == 0 || beta.arr[k][j] == 0) continue; 
17         mmp.arr[i][j]=
18             max(mmp.arr[i][j],alpha.arr[i][k]+beta.arr[k][j]);
19         }
20     }
21     }
22     return mmp;
23 }
24 
25 mat res;
26 long long fstpow(long long pw){
27     hh[0] = G;pw *= 2;
28     int bit = 0;
29     while((1ll<<bit) <= pw){
30     hh[bit+1] = hh[bit]*hh[bit];bit++;
31     int flag = 0;
32     for(int i=1;i<=n;i++) if(hh[bit].arr[1][i] >= m) flag = 1;
33     if(flag) break;
34     }
35     return bit;
36 }
37 
38 void read(){
39     scanf("%d%lld",&n,&m);
40     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lld",&G.arr[i][j]);
41 }
42 
43 void work(){
44     int z = fstpow(m);
45     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) res.arr[i][j] = 0;
46     long long ans = (1ll<<z);
47     long long now = 0;
48     while((--z) >= 0){
49     mat maye = res*hh[z];int flag = 0;
50     for(int i=1;i<=n;i++) if(maye.arr[1][i] >= m){flag = 1;break;}
51     if(flag) ans = now+(1ll<<z);
52     else now += (1ll<<z),res = maye;
53     }
54     printf("%lld\n",ans);
55 }
56 
57 int main(){
58     int Tmp; scanf("%d",&Tmp);
59     while(Tmp--){
60     read();
61     work();
62     }
63     return 0;
64 }

 

posted @ 2019-02-18 20:23  menhera  阅读(169)  评论(0编辑  收藏  举报