HDU6395-Sequence 矩阵快速幂+除法分块

Posted cwolf9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6395-Sequence 矩阵快速幂+除法分块相关的知识,希望对你有一定的参考价值。

目录

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

Catalog

Problem:Portal传送门

?原题目描述在最下面。

Solution:

?一看矩阵快速幂,再一看怎么多一个变项?(? frac{p}{n}?)
?我去,(? frac{p}{n}?)这不是前几天写过的一道除法分块经典题吗?
?关于除法分块,请看这里:GYM101652
?然后,就没有然后了~



技术分享图片

AC_Code:

#include<bits/stdc++.h>
#define mme(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int MXN = 5e5+7;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int n;
LL A,B,C,D,P;
struct lp{
  LL ar[3][3];
}aa,bb,cc;
lp multi(lp a,lp b){
  lp c;
  memset(c.ar,0,sizeof(c.ar));
  for(int k = 0; k < 3; ++k){
    for(int i = 0; i < 3; ++i){
      for(int j = 0; j < 3; ++j){
        c.ar[i][j] += a.ar[i][k]*b.ar[k][j];
        if(c.ar[i][j]>=MOD)c.ar[i][j] %= MOD;
      }
    }
  }
  return c;
}
lp ksm(lp a,LL b){
  lp res;
  for(int i = 0; i < 3; ++i){
    for(int j = 0; j < 3; ++j){
      res.ar[i][j] = (i==j);
    }
  }
  while(b){
    if(b&1)res = multi(res,a);
    a = multi(a, a);
    b>>=1;
  }
  return res;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("E://ADpan//in.in", "r", stdin);
    //freopen("E://ADpan//out.out", "w", stdout);  
#endif
  int tc = 0;
  int tim;
  scanf("%d", &tim);
  while(tim--){
    scanf("%lld%lld%lld%lld%lld%d", &A,&B,&C,&D,&P,&n);
    if(n == 1){
      printf("%lld
", A);
      continue;
    }else if(n == 2){
      printf("%lld
", B);
      continue;
    }else if(n == 3){
      printf("%lld
", (B*D%MOD+A*C%MOD+P/3)%MOD);
      continue;
    }
    /*aa.ar[3][3] = {
      {D,1LL,0LL},
      {C,0LL,0LL},
      {xLL,0LL,1LL},
    };*/
    memset(aa.ar,0,sizeof(aa.ar));
    memset(bb.ar,0,sizeof(bb.ar));
    aa.ar[0][0]=D;
    aa.ar[1][0]=C;
    aa.ar[0][1]=1;
    aa.ar[2][2]=1;
    bb.ar[0][0]=B;
    bb.ar[0][1]=A;
    bb.ar[0][2]=1;
    /*bb.ar[3][3] = {
      {B,A,1},
    };*/

    //这是参考大佬的写法一
    for(LL l = 3, r; l <= n; l = r + 1){
      if(P/l) r = min(P/(P/l),n*1LL);
      else r = n;
      aa.ar[2][0] = P/l;
      cc = ksm(aa, r-l+1);
      bb = multi(bb, cc);
    }
    
    /*这是我本来繁琐的写法
    for(LL l = 3, r; l <= P; l = r + 1){
      r = min(P/(P/l),n*1LL);
      aa.ar[2][0] = P/l;
      cc = ksm(aa, r-l+1);
      bb = multi(bb, cc);
      if(r == n * 1LL)break;
    }
    if(P <= n - 1){
      LL m = n - (P+1)+1;
      aa.ar[2][0] = 0;
      if(P<3)m = n-2;
      cc = ksm(aa, m);
      bb = multi(bb, cc);
    }*/
    printf("%lld
", bb.ar[0][0]);
  }
  return 0;
}


Problem Description:

技术分享图片






以上是关于HDU6395-Sequence 矩阵快速幂+除法分块的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)

HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)——2016 ACM/ICPC Asia Regional Shenyang Online

hdu 1852(快速幂模+有除法的时候取模的公式)

一些特殊的矩阵快速幂 hdu5950 hdu3369 hdu 3483

求幂大法,矩阵快速幂,快速幂模板题--hdu4549

HDU 5690 矩阵快速幂