题目描述
小A来到了一个陌生的城镇,这个城镇与其它城镇之间构成了集群。城镇之间的路径都是单向的,而小A每一天都能由一个城镇走到另外一个城镇。小A将会连续走k天,直到抵达某个城镇。也许他并不能走到这个城镇,那么可以认为不存在这样的路径,也就是路径数为0。否则就会有若干条路径可以抵达某个城镇。现在他想知道,如果他从给定某个城市出发,k天之后到达其它城镇的路径的总和是多少。数据不保证没有重边,也就是说可能每一天从一个城镇到另外一个城镇之间会有多条路径。路径总和可能会非常大,对答案模上1000000007。
输入描述:
第一行三个整数N,M,K,S分别表示一共有N个城镇,城镇之间有M条单向边。K表示小A连续走K天。S表示小A出发的那个城镇。接下来的M行每行两个整数u,v表示从城镇u连了一条有向边到城镇v。第一行三个整数N,M,K,S分别表示一共有N个城镇,城镇之间有M条单向边。K表示小A连续走K天。S表示小A出发的那个城镇。接下来的M行每行两个整数u,v表示从城镇u连了一条有向边到城镇v。
输出描述:
一行输出一个结果,表示小A到其余城镇路径数的总和。一行输出一个结果,表示小A到其余城镇路径数的总和。
示例1
输入
复制
4 5 2 1
1 2
1 3
2 3
4 1
3 4
输出
复制
2
说明
经过2天,小A可以走到3号城镇或者4号城镇,到3号城镇的路径有一条是1-2-3,到4号城镇的路径也是一条是1-3-4,共计有两条路径。
备注:
1≤N≤100, 1≤K≤1e9
思路:离散中的矩阵来做,用快速幂即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=110,mod=1e9+7;
int n,k,m,s;
struct Matrix{
long long Mat[maxn][maxn];
Matrix(){
memset(Mat,0,sizeof(Mat));
}
Matrix operator *(Matrix a){
Matrix res;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
res.Mat[i][j]=(res.Mat[i][j]+Mat[i][k]*a.Mat[k][j])%mod;
}
}
}
return res;
}
};
Matrix qmi(int k,Matrix base){
Matrix ans;
for(int i=1;i<=n;i++){
ans.Mat[i][i]=1;
}
while(k){
if(k&1) ans=ans*base;
k>>=1;
base=base*base;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>k>>s;
int u,v;
Matrix base;
for(int i=1;i<=m;i++){
cin>>u>>v;
base.Mat[u][v]++;
}
Matrix solve=qmi(k,base);
long long sum=0;
for(int i=1;i<=n;i++){
sum=(sum+solve.Mat[s][i])%mod;
}
sum=(sum-solve.Mat[s][s]+mod)%mod;
cout<<sum<<endl;
}