http://acm.hdu.edu.cn/showproblem.php?pid=2254
矩阵乘法两个经典问题的综合题,还要离散化和处理边界,好题啊好题
题意容易理解错,每一天是独立的,所以根据加法原理方案数是G^1+G^2+...+G^t
/* 此题要求 (G^1+G^2+...+G^t2)-(G^1+G^2+...+G^(t1-1)) 求和的方法是再次二分,k=6时 G + G^2 + G^3 + G^4 + G^5 + G^6 = G + G^2 + G^3 + G^3 * (G + G^2 + G^3) = (1 + G^3) * (G + G^2 + G^3) 这样计算可以使k的规模减少一半,快速幂求出G^3后可递归计算G+G^2+G^3,即得答案 */ #include <iostream> #include <cstdio> #include <cstring> #include <map> using namespace std; #define MOD 2008 #define Mat 35 //矩阵大小 struct mat{//矩阵结构体,a表示内容,r行c列 矩阵从1开始 int a[Mat][Mat]; int r, c; mat() { r = c = 0; memset(a, 0, sizeof(a)); } }; void print(mat m) { //printf("%d\n", m.size); for(int i = 0; i < m.r; i++) { for(int j = 0; j < m.c; j++) printf("%d ", m.a[i][j]); putchar('\n'); } } mat mul(mat m1, mat m2, int mod) { mat ans = mat(); ans.r = m1.r, ans.c = m2.c; for(int i = 1; i <= m1.r; i++) for(int j = 1; j <= m2.r; j++) if(m1.a[i][j]) for(int k = 1; k <= m2.c; k++) ans.a[i][k] = (ans.a[i][k] + m1.a[i][j] * m2.a[j][k]) % mod; return ans; } mat add(mat m1, mat m2, int mod) { mat ans = mat(); ans.r = ans.c = m1.r; for(int i = 1; i <= m1.r; i++) for(int j = 1; j <= m1.r; j++) ans.a[i][j] = (m1.a[i][j] + m2.a[i][j]) % mod; return ans; } mat quickmul(mat m, int n, int mod) { mat ans = mat(); for(int i = 1; i <= m.r; i++) ans.a[i][i] = 1; ans.r = m.r, ans.c = m.c; while(n) { if(n & 1) ans = mul(m, ans, mod); m = mul(m, m, mod); n >>= 1; } return ans; } mat A; mat sum(mat m, int n, int mod) { //m^1+m^2+...+m^n if(n == 1) return m; if(n & 1) return add(quickmul(m, n, mod), sum(m, n-1, mod), mod); //是否加m^n else return mul(add(quickmul(m, n>>1, mod), A, mod), sum(m, n>>1, mod), mod); // (1 + m^(n/2)) * (m + m^2 +...+ m^(n/2)) } /* 初始化ans矩阵 mat ans = mat(); ans.r = R, ans.c = C; ans = quickmul(ans, n, mod); */ int main() { A = mat(); for(int i = 1; i <= 30; i++) A.a[i][i] = 1; int n; while(~scanf("%d", &n)) { mat G = mat(); G.r = G.c = 30; map <int, int> mp; int rank = 1; while(n--) { int a, b; scanf("%d%d", &a, &b); if(!mp[a]) mp[a] = rank++; if(!mp[b]) mp[b] = rank++; G.a[mp[a]][mp[b]]++; } int k; scanf("%d", &k); for(int i = 0; i < k; i++) { int v1, v2, t1, t2; scanf("%d%d%d%d", &v1, &v2, &t1, &t2); v1 = mp[v1]; v2 = mp[v2]; if(t1 > t2) swap(t1, t2); if(!t1){ if(!t2) puts("0"); else { int ans = sum(G, t2, MOD).a[v1][v2]; printf("%d\n", ans); } } else if(t1 == 1) { int ans = sum(G, t2, MOD).a[v1][v2]; printf("%d\n", ans); } else { int ans1 = sum(G, t1-1, MOD).a[v1][v2]; int ans2 = sum(G, t2, MOD).a[v1][v2]; printf("%d\n", (ans2 - ans1 + MOD) % MOD); } } } return 0; }