[bzoj3583]杰杰的女性朋友

问题即求$\sum_{i=0}^{d}(out\cdot in)^{d}_{u,v}$,进而转换为$[u=v]+(out\cdot \sum_{i=0}^{d-1}(in\cdot out)^{i}\cdot in)_{u,v}$

注意到$in\cdot out$是$k\times k$的,并使用类似矩阵快速幂的方式计算幂次前缀和即可

时间复杂度为$o(nk^{2}+qk^{3}\log d)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1005
 4 #define M 25
 5 #define mod 1000000007
 6 #define ll long long
 7 int n,m,q,x,y,z,ans,out[N][M],in[M][N],st[N];
 8 struct mat{
 9     int a[M][M];
10     mat(int p=0){
11         memset(a,0,sizeof(a));
12         for(int i=1;i<=m;i++)a[i][i]=p;
13     }
14 }a,s,sum;
15 mat add(mat &a,mat b){
16     mat ans;
17     for(int i=1;i<=m;i++)
18         for(int j=1;j<=m;j++)ans.a[i][j]=(a.a[i][j]+b.a[i][j])%mod;
19     return ans;
20 }
21 mat mul(mat &a,mat &b){
22     mat ans;
23     for(int i=1;i<=m;i++)
24         for(int j=1;j<=m;j++)
25             for(int k=1;k<=m;k++)ans.a[i][k]=(ans.a[i][k]+(ll)a.a[i][j]*b.a[j][k])%mod;
26     return ans;
27 }
28 int main(){
29     scanf("%d%d",&n,&m);
30     for(int i=1;i<=n;i++){
31         for(int j=1;j<=m;j++)scanf("%d",&out[i][j]);
32         for(int j=1;j<=m;j++)scanf("%d",&in[j][i]);
33     }
34     for(int i=1;i<=m;i++)
35         for(int j=1;j<=n;j++)
36             for(int k=1;k<=m;k++)a.a[i][k]=(a.a[i][k]+(ll)in[i][j]*out[j][k])%mod;
37     scanf("%d",&q);
38     while (q--){
39         scanf("%d%d%d",&x,&y,&z);
40         for(;z;z>>=1)st[++st[0]]=(z&1);
41         s=1,sum=0;
42         while (st[0]){
43             sum=add(sum,mul(s,sum)),s=mul(s,s);
44             if (st[st[0]])sum=add(s,sum),s=mul(s,a);
45             st[0]--;
46         } 
47         ans=(x==y);
48         for(int i=1;i<=m;i++)
49             for(int j=1;j<=m;j++)ans=(ans+(ll)out[x][i]*sum.a[i][j]%mod*in[j][y])%mod;
50         printf("%d\n",ans);
51     }
52     return 0;
53 }
View Code

 

posted @ 2022-03-11 20:25  PYWBKTDA  阅读(78)  评论(0编辑  收藏  举报