标签:out ini 题意 pop long rac 结果 div eof
题目链接:传送门
题意:
一个图有n个顶点。已知邻接矩阵。问点能够反复用长度小于m的路径有多少。
分析:
首先我们知道了邻接矩阵A。那么A^k代表的就是长度为k的路径有多少个。
那么结果就是A^0+A^1+A^2+...+A^m。
然后我们能够构造一个矩阵来帮助我们求解。
X = | A , E |
| 0 , E |
==> 然后X^m 的矩阵的右上角的矩阵代表的就是A^0+A^1+A^2+...+A^m。
当然A^0+A^1+A^2+...+A^m,也能够用二分来求。
代码例如以下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 51*2;
const int mod = 2015;
typedef long long LL;
struct matrix{
int a[maxn][maxn];
matrix(){
memset(a,0,sizeof(a));
}
};
matrix I;
void init(){
for(int i=0;i<maxn;i++)
I.a[i][i]=1;
}
int n,m;
matrix multi(matrix A,matrix B){
matrix C;
for(int i=0;i<2*n;i++){
for(int j=0;j<2*n;j++){
for(int k=0;k<2*n;k++){
C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]);
}
C.a[i][j]%=mod;
}
}
return C;
}
matrix add(matrix A,matrix B){
matrix C;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
C.a[i][j]=(A.a[i][j]+B.a[i][j])%mod;
}
}
return C;
}
int quick_mod(matrix A,int b){
matrix ans = I;
while(b){
if(b&1) ans = multi(ans,A);
b>>=1;
A=multi(A,A);
}
int sum = 0;
for(int i=0;i<n;i++){
for(int j=n;j<n*2;j++)
sum=sum+ans.a[i][j];
}
// cout<<"----------ans------------"<<endl;
// for(int i=0;i<2*n;i++){
// for(int j=0;j<2*n;j++)
// cout<<ans.a[i][j]<<" ";
// cout<<endl;
// }
// cout<<"----------ans------------"<<endl;
return sum%mod;
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
matrix A,B;
for(int i=0;i<n;i++){
int k,u;
scanf("%d",&k);
while(k--){
scanf("%d",&u);
A.a[i][--u]=1;
}
}
for(int i=0;i<n;i++) A.a[i][i+n]=1;
for(int i=n;i<2*n;i++) A.a[i][i]=1;
// cout<<"----------A------------"<<endl;
// for(int i=0;i<2*n;i++){
// for(int j=0;j<2*n;j++)
// cout<<A.a[i][j]<<" ";
// cout<<endl;
// }
// cout<<"----------A------------"<<endl;
int sum = quick_mod(A,m);
printf("%d\n",sum+1);
}
return 0;
}
标签:out ini 题意 pop long rac 结果 div eof
原文地址:http://www.cnblogs.com/yutingliuyl/p/7086947.html