题意:
一个有向图,两个顶点间可能有多条边,视为不同的路径,问从v1到v2之间的路径长度大小在[t1,t2]的方案数mod 2008。
输入n条边,p1,p2。因为p1,p2<2^32。但是总的顶点数不超过30.所以进行离散化即可。而且有可能t1>t2,所以要判断一下。
输入的v1,v2可能也不在有向图内。
分析:
先进行顶点的离散化,每次遇到相同的边就+1,然后输入v1,v2,t1,t2.判断v1,v2是否在图内,不在则直接输出0.
然后判断t1,t2的大小。如果t1>t2,就交换下。如果此时t2仍然等于0,就是t1=0,t2=0,直接输出0,即可。
然后利矩阵进行快速求解(A^1+A^2+....A^ t ),然后再(A^1+A^2+...A^t2)-(A^1+A^2+....A^(t1-1))得到(A^t1+A^(t1+1)+....A^t2).
/*//
快速矩阵幂 HDU 2254
//*/
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
int mod=2008,n;
struct Matrix
{
int m[32][32];
void clear()
{
memset(m,0,sizeof(m));
}
}E, Z;
Matrix Mut(Matrix A, Matrix B)//矩阵相乘
{
Matrix ans;
for (int i = 1; i<= n; i++)
for (int j = 1; j<= n; j++)
{
ans.m[i][j] = 0;
for (int k =1; k<= n; k++)
{
ans.m[i][j] += ((A.m[i][k])*(B.m[k][j]));
ans.m[i][j] %= mod;
}
}
return ans;
}
Matrix Add(Matrix A, Matrix B)//矩阵相加
{
Matrix ans;
for (int i = 1; i<= n; i++)
for (int j = 1; j<= n; j++)
ans.m[i][j] = (A.m[i][j] + B.m[i][j]) % mod;
return ans;
}
Matrix Pow(Matrix A, LL b)//矩阵的幂
{
Matrix t = A, ans = E;
while (b)
{
if (b % 2) ans = Mut(ans, t);
b /= 2;
t = Mut(t, t);
}
return ans;
}
Matrix solve(Matrix A, int b)//矩阵的幂之和
{
if (b == 0)
return E;
else if (b == 1)
return A;
else if (b == 2)
return Add(A, Mut(A, A));
else if (b % 2 == 1)
return Add(Pow(A, b), solve(A, b - 1));
else
{
Matrix ans = solve(A, b / 2);
Matrix C = Pow(A, b / 2);
Matrix B = Mut(ans, C);
return Add(B, ans);
}
}
map<LL,int>s;
int main()
{
// freopen("in.txt", "r", stdin);
Matrix A,ans1,ans2;
LL v1,v2,x,y;
int t1,t2,q,m;
while(scanf("%d",&m)!=EOF)
{
n=0;
s.clear();A.clear();
for(int i=0;i<m;i++)
{
scanf("%I64d %I64d",&x,&y);
if(s[x]==0||s[y]==0)//离散化处理
{
if(s[x]==0)
s[x]=++n;
if(s[y]==0)
s[y]=++n;
}
A.m[s[x]][s[y]]++;
}
for (int i = 1; i<= n; i++)
for (int j = 1; j<= n; j++)
E.m[i][j] = (i == j);
scanf("%d",&q);
while(q--)
{
scanf("%I64d %I64d %d %d",
&v1,&v2,&t1,&t2);
if(t1>t2)
swap(t1,t2);
if(s[v1]==0||s[v2]==0)//点不在图内
{
printf("0\n");
continue;
}
if(t2==0)//t1=0,t2=0
{
printf("0\n");
continue;
}
int a1=s[v1],a2=s[v2];
if(t1 > 1)
{
ans1=solve(A, t2);
ans2=solve(A, t1-1);
printf("%d\n",(ans1.m[a1][a2]-ans2.m[a1][a2] + mod) % mod);
}
else
{
ans1=solve(A, t2);
printf("%d\n", ((ans1.m[a1][a2] % mod) + mod) % mod);
}
}
}
return 0;
}