http://acm.hdu.edu.cn/showproblem.php?pid=2254
解题思路:求t1->t2天内,v1->v2一共有多少条的路径。就是要用到离散数学的可达矩阵的n次幂各元素的值就是经过n条路可以到达该点。所以说这道题说白了就是叫你求 A^t1+a^(t1+1)+……A^(t2),输出 v1v2该元素的值模2008(注意负数的处理).所以就是要用到矩阵降幂+二分求和。
#include <stdio.h> #include <string.h> #define size 30 const int MOD = 2008; int len; __int64 city[size]; struct Mat { int mat[size][size]; }e,init; int FindCity(__int64 x,bool flag) { int i; for (i=0;i<len;i++) if(city[i]==x) return i; if (flag) { city[len++] = x; return len-1; } return 50;/*没找到城市*/ } Mat operator+(Mat a,Mat b) { Mat c; int i,j; for (i=0;i<len;i++) { for(j=0;j<len;j++) c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD; } return c; } Mat operator*(Mat a,Mat b) { int i,j,k; Mat c; for (i=0;i<len;i++) { for (j=0;j<len;j++) { c.mat[i][j] = 0; for(k=0;k<len;k++) c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%MOD; } } return c; } Mat operator^(Mat a,int x) { Mat p = e,q = a; while (x) { if(x&1) p = p*q; x>>=1; q = q*q; } return p; } Mat solve(Mat a,int p) { if(p==1) return a; else if(p&1) return (a^p)+solve(a,p-1); else return ((a^(p>>1))+e)*solve(a,p>>1); } int main() { __int64 v1,v2; int t1,t2,i,j,n,k,c,locate1,locate2,sum; Mat tem1,tem2; for(i=0;i<size;i++) for(j=0;j<size;j++) e.mat[i][j] = (i==j); while (scanf("%d",&n)!=EOF) { len = 0; memset(&init,0,sizeof(init)); while (n--) { scanf("%I64d%I64d",&v1,&v2); locate1 = FindCity(v1,1); locate2 = FindCity(v2,1); init.mat[locate1][locate2]++; } scanf("%d",&k); while (k--) { scanf("%I64d%I64d%d%d",&v1,&v2,&t1,&t2); if(t1>t2) c = t1,t1 = t2,t2 = c; locate1 = FindCity(v1,0); locate2 = FindCity(v2,0); if(locate1==50||locate2==50||(t1==0&&t2==0)) printf("0/n"); else { if (t1>1) { tem1 = solve(init,t2); tem2 = solve(init,t1-1); sum = (tem1.mat[locate1][locate2]%MOD-tem2.mat[locate1][locate2]%MOD)%MOD; } else { tem1 = solve(init,t2); sum = tem1.mat[locate1][locate2]%MOD; } if(sum<0) sum+=MOD; printf("%d/n",sum); } } } return 0; }