 /**//*
给出一个图,询问T时间内from->to的方法数。t<=10^9 , n<=50
但每个点向外的边有周期性,在某些时刻会开,某些时刻没有 周期<=6 人可在点停留

请教hhanger的 Orz
矩阵M[t]表示t时刻i->j的方法数 那么M[t] = M[t-1]*A[t] A[t]为t时刻图的邻接表
M[0] = I
M[1] = M[0]*A[1]
M[2] = M[1]*A[2] = A[1]*A[2]

M[60] = A[1]*A[2] A[60]
M[61] = A[1]*A[2] *A[60]*A[61]

注意到,每个点的周期是[1,6] 所以60是他们的LCM周期 所以A[61] = A[1]
M[61] = M[60] * A[1]
.
M[k*60 + t0] = M[60]^k * M[t0]
对于这个幂就可以用矩阵乘法了
对T/60个M[60]矩阵用矩阵乘法 , 剩下的T%60就是M[T%60]
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<cstdlib>
#include<iostream>

using namespace std;

const int INF = 1000000000;
const int MOD = 100000007;
const int MAXN = 50;


int n , T;
long long U[MAXN][MAXN];
long long A[65][MAXN][MAXN];


void imul(long long C[][MAXN] , long long A[][MAXN] , long long B[][MAXN]) // C = A * B
  {
 long long R[MAXN][MAXN] = {0};
for(int k = 0 ; k < n; k++)
for(int i = 0 ; i < n ; i++)
if(A[i][k])
 {
for(int j = 0 ; j <n; j ++)
R[i][j] += A[i][k] * B[k][j];
}
for(int i = 0 ; i < n; i++)
for(int j = 0 ; j < n ; j++)
C[i][j] = R[i][j] % MOD;
}

void ipow(long long R[][MAXN] , int K)
  {
if(K == 0)
 {
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < n ; j++)
R[i][j] = (i==j);
return ;
}
if(K == 1)
 {
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < n ; j++)
R[i][j] = U[i][j];
return ;
}
ipow(R , K / 2);
imul(R , R , R);
if(K&1)imul(R , R , U);
}


int main()
  {

#ifdef ONLINE_JUDGE
#else
freopen("in", "r", stdin);
#endif

int from , to;
while( ~scanf("%d%d%d%d",&n,&T,&from,&to) )
 {
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < n ; j++)
scanf("%d",&A[0][i][j]);
for(int j = 0 ; j < n ; j++)
A[0][to][j] = 0;

int num , x;
for(int i = 0 ; i < n ; i++)
 {
scanf("%d",&num);
for(int jj = 1 ; jj <= num ; jj++)
 {
scanf("%d",&x);
for(int k = 0 ; num*k + jj <= 60 ; k++)
 {
for(int j = 0 ; j < n ;j++)
A[num*k + jj][i][j] = x & A[0][i][j];
A[num*k + jj][i][i] = 1;
}
}
}

int limit = min(60 , T);

for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < n; j++)
A[0][i][j] = (i==j);
for(int k = 1 ; k <= limit ; k++)
 {
imul(A[k] , A[k-1] , A[k]);//M[k] = M[k-1] * A[k]
}
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < n; j++)
U[i][j] = A[60][i][j];//M[60]

int K = T / 60 , left = T % 60;
long long R[MAXN][MAXN];
ipow(R,K);
imul(R,R,A[left]);
printf("%lld\n",R[from][to]);
}
return 0;
}


|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|