【洛谷 P1707】 刷题比赛 (矩阵加速)

题目连接
很久没写矩阵加速了,复习一下,没想到是一道小毒瘤题。

状态矩阵\(a[k],b[k],c[k],a[k+1],b[k+1],c[k+1],k,k^2,w^k,z^k,1\)
转移矩阵

  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
  0, q, 0, 0, p, 1, 1, t, r, 0, 0, 1,
  0, 0, v, 0, 1, u, 1, 0, 0, 1, 0, 0,
  0, 0, 0, y, 1, 1, x, 1, 0, 0, 1, 2,
  0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
  0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 1,
  0, 0, 0, 0, 0, 0, 0, 0, 0, w, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1

手写不易。

#include <cstdio>
#include <cstdlib>
#include <cstring>
// a[k],b[k],c[k],a[k+1],b[k+1],c[k+1],k,k^2,w^k,z^k,1
int u, v, p, q, r, t, x, w, z, y;
typedef long long ll;
ll n, k;
ll f[12], tmp[12], temp[12][12], dp[12][12];
inline ll Slow_Mul(ll a, ll b){
    ll ans = 0;
    while(b){
      if(b & 1) ans = (ans + a) % k;
      b >>= 1;
      a = (a + a) % k;
    }
    return ans;
}
inline void Mult(){
    for(int i = 1; i <= 11; ++i){
       tmp[i] = 0;
       for(int j = 1; j <= 11; ++j)
          (tmp[i] += Slow_Mul(f[j], dp[i][j])) %= k;
    }
    for(int i = 1; i <= 11; ++i)
       f[i] = tmp[i];
}
inline void Self(){
    for(int i = 1; i <= 11; ++i)
       for(int j = 1; j <= 11; ++j){
          temp[i][j] = 0;
          for(int l = 1; l <= 11; ++l)
             (temp[i][j] += Slow_Mul(dp[i][l], dp[l][j])) %= k;
       }
    for(int i = 1; i <= 11; ++i)
       for(int j = 1; j <= 11; ++j)
          dp[i][j] = temp[i][j];
}
inline void Fast_Pow(){
    n -= 2;
    while(n){
      if(n & 1) Mult();
      n >>= 1;
      Self();
    }
}
int main(){
    scanf("%lld%lld%d%d%d%d%d%d%d%d%d%d", &n, &k, &p, &q, &r, &t, &u, &v, &w, &x, &y, &z);
    ll xs[12][12] = 
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
  0, q, 0, 0, p, 1, 1, t, r, 0, 0, 1,
  0, 0, v, 0, 1, u, 1, 0, 0, 1, 0, 0,
  0, 0, 0, y, 1, 1, x, 1, 0, 0, 1, 2,
  0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
  0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 1,
  0, 0, 0, 0, 0, 0, 0, 0, 0, w, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
    memcpy(dp, xs, sizeof dp);
    f[1] = f[2] = f[3] = f[11] = 1; f[4] = f[5] = f[6] = 3; f[9] = w; f[10] = z; f[7] = 1; f[8] = 1;
    Fast_Pow();
    printf("nodgd %lld\nCiocio %lld\nNicole %lld\n", f[4], f[5], f[6]);
    return 0;
}

posted @ 2018-10-15 11:56  Qihoo360  阅读(126)  评论(0编辑  收藏  举报
You're powerful!