Matrix Multiplication (& Quick Power)
Description
求v1到v2两个点之间,长度为t1~t2的路径总数。
Type
Matrix Multiplication
Quick Power
Analysis
这题可以用传递闭包的思想。
即这张图邻接矩阵的n次幂,即为两点之间长度为n的路径总数。
然后矩阵乘法+快速幂求解。
但是这道题有几个要注意的:
- 题目中城市的总数小于30,这保证了我们构造的矩阵不会太大。
但是输入中的城市p1、p2的取值范围是int的范围。
因此我们要用一个map,把城市映射到0~30的点上。
- 这题的数据规模较大,在计算t1~t2路径总数时,不能对[t1, t2]中的每一点都做矩阵乘法+快速幂,否则会TLE。
正确方法应该是,计算出指数为t1时的邻接矩阵,然后指数递增到t2,其中对所求的路径求和。
- 注意t1 = 0的情况,这时候路径数应该为0。
// HDOJ 2254
// 奥运
// by A Code Rabbit
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
const int MAXO = 32;
const int MOD = 2008;
template <typename T>
struct Matrix {
T e[MAXO][MAXO];
int o;
Matrix(int ord) { memset(e, 0, sizeof(e)); o = ord; }
Matrix operator*(const Matrix& one) {
Matrix res(o);
for (int i = 0; i < o; i++)
for (int j = 0; j < o; j++)
for (int k = 0; k < o; k++)
res.e[i][j] += e[i][k] * one.e[k][j];
return res;
}
Matrix operator%(int mod) {
for (int i = 0; i < o; i++)
for (int j = 0; j < o; j++)
e[i][j] %= mod;
return *this;
}
};
template <typename T>
T QuickPower(T rdx, int exp, int mod) {
T res = rdx;
exp--;
while (exp) {
if (exp & 1) res = res * rdx % mod;
exp >>= 1;
rdx = rdx * rdx % mod;
}
return res;
}
int n;
int p1, p2;
int k;
int v1, v2, t1, t2;
map<int, int> city;
int tot_city;
int GetPos(int x);
int main() {
while (scanf("%d", &n) != EOF) {
// Input and count.
city.clear();
tot_city = 0;
Matrix<int> mat_one(MAXO);
for (int i = 0; i < n; i++) {
scanf("%d%d", &p1, &p2);
int pos1 = GetPos(p1); int pos2 = GetPos(p2);
mat_one.e[pos1][pos2]++;
}
mat_one.o = tot_city;
// Input, run and output.
scanf("%d", &k);
for (int i = 0; i < k; i++) {
scanf("%d%d%d%d", &v1, &v2, &t1, &t2);
if (city.find(v1) == city.end() || city.find(v2) == city.end()) {
printf("0\n");
continue;
}
Matrix<int> mat_ans(tot_city);
if (t1) {
mat_ans = QuickPower(mat_one, t1, MOD);
} else {
for (int i = 0; i < mat_ans.o; i++)
mat_ans.e[i][i] = 1;
}
int pos1 = city[v1]; int pos2 = city[v2];
int sum = !t1 ? 0 : mat_ans.e[pos1][pos2];
for (int j = t1 + 1; j <= t2; j++) {
mat_ans = mat_ans * mat_one % MOD;
sum += mat_ans.e[pos1][pos2];
}
printf("%d\n", sum % MOD);
}
}
return 0;
}
int GetPos(int x) {
if (city.find(x) == city.end())
city[x] = tot_city++;
return city[x];
}