bzoj3583: 杰杰的女性朋友

原来写的等比矩阵求和是$log^2{}$的,$log{}$的就把最高次按照从低位到高位分成$log{}$个递增的$2$的整次幂的长度

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<iostream>
  6 
  7 using namespace std;
  8 
  9 template<typename Q> Q &read(Q &x) {
 10     static char c, f;
 11     for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1;
 12     for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
 13     if(f) x = -x; return x;
 14 }
 15 template<typename Q> Q read() {
 16     static Q x; read(x); return x;
 17 }
 18 
 19 const int N = 20, mod = 1000000007;
 20 
 21 int m; 
 22 struct Matrix {
 23     int da[N][N];
 24 }I, base;
 25 
 26 void addit(int &a, int b) {
 27     if((a += b) >= mod) a -= mod;
 28 }
 29 
 30 typedef long long LL;
 31 
 32 Matrix operator * (const Matrix &a, const Matrix &b) {
 33     Matrix c;
 34     for(int i = 0; i < m; i++) {
 35         for(int j = 0; j < m; j++) {
 36             c.da[i][j] = 0;
 37             for(int k = 0; k < m; k++) {
 38                 addit(c.da[i][j], (LL) a.da[i][k] * b.da[k][j] % mod);
 39             }
 40         }
 41     }
 42     return c;
 43 }
 44 
 45 Matrix operator + (const Matrix &a, const Matrix &b) {
 46     Matrix c;
 47     for(int i = 0; i < m; i++) {
 48         for(int j = 0; j < m; j++) {
 49             c.da[i][j] = 0;
 50             addit(c.da[i][j], a.da[i][j]);
 51             addit(c.da[i][j], b.da[i][j]);
 52         }
 53     }
 54     return c;
 55 }
 56 
 57 Matrix solve(Matrix a, int n) {
 58     Matrix c = I, v = I, b = a;
 59     for(; ; ) {
 60         if(n & 1) c = c + b * v, v = v * a;
 61         if(!(n >>= 1)) return c;
 62         b = b * (a + I);
 63         a = a * a;
 64     }
 65 }
 66 
 67 int in[N][2010], out[2010][N];
 68 
 69 int main() {
 70 #ifdef DEBUG
 71     freopen("in.txt", "r", stdin);
 72     freopen("out.txt", "w", stdout);
 73 #endif
 74     
 75     int n;
 76     scanf("%d%d", &n, &m);
 77     for(int i = 0; i < n; i++) {
 78         for(int j = 0; j < m; j++) {
 79             scanf("%d", out[i] + j);
 80         }
 81         for(int j = 0; j < m; j++) {
 82             scanf("%d", in[j] + i);
 83         }
 84     }
 85     
 86     int q; scanf("%d", &q);
 87     for(int i = 0; i < m; i++) {
 88         for(int j = 0; j < m; j++) {
 89             for(int k = 0; k < n; k++) {
 90                 addit(base.da[i][j], (LL) in[i][k] * out[k][j] % mod);
 91             }
 92         }
 93     }
 94     int ans[N];
 95     for(int i = 0; i < m; i++) I.da[i][i] = 1;
 96     while(q--) {
 97         int u, v, d; scanf("%d%d%d", &u, &v, &d);
 98         if(d == 0) printf("%d
", u == v);
 99         else {
100             memset(ans, 0, sizeof ans);
101             --u, --v;
102             Matrix c = solve(base, d - 1);
103             for(int j = 0; j < m; j++) {
104                 for(int k = 0; k < m; k++) {
105                     addit(ans[j], (LL) out[u][k] * c.da[k][j] % mod);
106                 }
107             }
108             int res = 0;
109             for(int i = 0; i < m; i++) {
110                 addit(res, (LL) ans[i] * in[i][v] % mod);
111             }
112             printf("%d
", res + (u == v));
113         }
114     }
115     
116     return 0;
117 }
View Code
原文地址:https://www.cnblogs.com/showson/p/5219185.html