![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) /**//*
给出一个图,询问T时间内from->to的方法数。t<=10^9 , n<=50
但每个点向外的边有周期性,在某些时刻会开,某些时刻没有 周期<=6 人可在点停留
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
请教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]
![](http://www.cppblog.com/Images/dot.gif)
M[60] = A[1]*A[2] A[60]
M[61] = A[1]*A[2] *A[60]*A[61]
![](http://www.cppblog.com/Images/dot.gif)
注意到,每个点的周期是[1,6] 所以60是他们的LCM周期 所以A[61] = A[1]![](http://www.cppblog.com/Images/dot.gif)
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>
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
using namespace std;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
const int INF = 1000000000;
const int MOD = 100000007;
const int MAXN = 50;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
int n , T;
long long U[MAXN][MAXN];
long long A[65][MAXN][MAXN];
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
void imul(long long C[][MAXN] , long long A[][MAXN] , long long B[][MAXN]) // C = A * B
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) long long R[MAXN][MAXN] = {0};
for(int k = 0 ; k < n; k++)
for(int i = 0 ; i < n ; i++)
if(A[i][k])
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
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;
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
void ipow(long long R[][MAXN] , int K)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) {
if(K == 0)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < n ; j++)
R[i][j] = (i==j);
return ;
}
if(K == 1)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
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);
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
int main()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#ifdef ONLINE_JUDGE
#else
freopen("in", "r", stdin);
#endif
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int from , to;
while( ~scanf("%d%d%d%d",&n,&T,&from,&to) )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
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;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int num , x;
for(int i = 0 ; i < n ; i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
scanf("%d",&num);
for(int jj = 1 ; jj <= num ; jj++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
scanf("%d",&x);
for(int k = 0 ; num*k + jj <= 60 ; k++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
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;
}
}
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int limit = min(60 , T);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
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++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) {
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]
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
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;
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
|
|
常用链接
随笔分类
Links
搜索
最新评论
![](/images/xml.gif)
|
|