HDU 5015 233 Matrix / 2014 ACM/ICPC Asia Regional Xi'an Online

来源:互联网 发布:php采集cookie设置 编辑:程序博客网 时间:2024/04/29 17:54

题目: LINK  

此题可以用矩阵快速幂做


用行向量[a1, b2, a3, a4, .... 233, 3] ,n+2个元素
再构造n+2 的方阵
1  1  1  1 ..... 0  0
0  1  1  1 ..... 0  0
0  0  1  1 ..... 0  0
0  0  0  1 ..... 0  0
  ................
1  1  1  1 ..... 10 0
0  0  0  0 ..... 1  1
左上角的n大小的方阵是上三角行的,多加的两列是为了控制233....33的,每次都可以算出来,
求方阵的m次幂,用初始行向量乘以结果方阵的第n列,就是结果了.
模拟一下就知道为什么这么做了.

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <string>#include <vector>#include <cmath>#include <queue>#include <map>#include <set>using namespace std; #define INF 1000000000typedef __int64 LL; #define N 15LL n, m, num[N]; #define mod 10000007struct node {LL mat[N][N]; }; node mul(node x, node y)  {      node ret;      memset(ret.mat, 0, sizeof(ret.mat));      for(int i=1; i<=n+2; i++) {          for(int j=1; j<=n+2; j++) {              for(int k = 1; k<=n+2; k++) {                  ret.mat[i][j] += x.mat[i][k]*y.mat[k][j];                  ret.mat[i][j] %= mod;              }          }      }      return ret ;  }  node pow_(node x, LL y)  {      node ret; for(int i = 0; i <= n+2; i++) {for(int j = 0; j <= n+2; j++) {if(i == j) ret.mat[i][j] = 1; else ret.mat[i][j] = 0; }}    while(y) {          if(y&1) {              ret = mul(ret, x);          }          y>>=1;          x = mul(x, x);      }      return ret;  }  int main() {#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin); #endif // ONLINE_JUDGEwhile(scanf("%I64d%I64d", &n, &m) != EOF) {for(int i = 1; i <= n; i++) scanf("%I64d", &num[i]); node S;memset(S.mat, 0, sizeof(S.mat)); for(int i = 1; i <= n; i++) {for(int j = n; j >= i; j--) S.mat[i][j] = 1; }for(int i = 1; i <= n; i++) S.mat[n+1][i] = 1; S.mat[n+1][n+1] = 10; S.mat[n+2][n+1] = S.mat[n+2][n+2] = 1; S = pow_(S, m); LL ans = 0; for(int i = 1; i <= n; i++) ans += num[i] * S.mat[i][n] % mod, ans %= mod; ans += (LL)233 * S.mat[n+1][n]; ans %= mod; ans += (LL) 3 * S.mat[n+2][n]; ans %= mod; printf("%I64d\n", ans); }return 0; }


0 0