hdu 6395 Sequence(矩阵快速幂 + 整除分块)

题意:
在这里插入图片描述
给出你如上递推式,让你求第 n n 项。
思路:
由于 p / n p/n 不是常数,我们不能直接用矩阵快速幂,根据整除分块的特点,我们分段进行矩阵快速幂即可。
构造转移矩阵

[ d c p / i 1 0 0 0 0 1 ] \begin{bmatrix} d& c & p/i\\ 1& 0 & 0\\ 0& 0 &1 \end{bmatrix}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
using namespace std;
#define ll long long
const int N = 1e5 +5;
#define LL long long
const LL mod = 1e9 + 7 ;
struct mat
{
    LL m[3][3];//矩阵大小
    mat() {
       memset(m,0,sizeof(m));
    }
    mat operator * (mat &a ) {//重载 * 运算符
       mat ans;
       for (int i=0 ;i < 3 ;i++  ){//矩阵乘法
          for (int k=0 ;k<3 ;k++) if(m[i][k]) {
              for (int j=0 ;j<3 ;j++) if(a.m[k][j]) {
                 ans.m[i][j]=(ans.m[i][j]+m[i][k]*a.m[k][j])%mod;//取模
              }
          }
       }
       return ans;
    }
};
mat mat_pow(mat a,LL b)//矩阵快速幂
{
    mat ans;
    for (int i=0 ;i < 3 ;i++ ) ans.m[i][i]=1;//单位阵
    while(b) {
        if (b&1) ans=ans*a;
        b=b>>1;
        a=a*a;
    }
    return ans;
}

int main(){
    int t;
    cin >> t;ll a,b,c,d,p,n;
    while(t --){
        cin >> a >> b >> c >> d >> p >> n;
        if(n == 1) cout<<a<<endl;
        else if(n == 2) cout<<b<<endl;
        else {
            LL mm[3][3] = {
                {d,c,0},
                {1,0,0},
                {0,0,1},
            };
            mat ans ;
            for(int i = 0;i < 3;++i){
                for(int j = 0;j < 3;++j)
                    ans.m[i][j] = mm[i][j];
            }
            bool rt = 0;
            for(ll l = 3,r;l <= n;l = r + 1){

                if(p / l == 0){
                    mat tmp;
                    tmp = ans;
                    tmp = mat_pow(tmp,n-l+1);
                    rt = 1;
                    ll res = (tmp.m[0][0] * b % mod+ tmp.m[0][1] *a%mod+tmp.m[0][2]%mod)%mod;
                    cout<<res<<endl;break;
                }
                else{
                    r = min(p   /(p/l),n);
                    mat tmp;
                    tmp = ans;
                    tmp.m[0][2] = p/l;
                    tmp = mat_pow(tmp,r - l + 1);
                    ll B = (tmp.m[0][0] * b % mod+ tmp.m[0][1] *a%mod+tmp.m[0][2]%mod)%mod;
                    ll A = (tmp.m[1][0] * b % mod+ tmp.m[1][1] *a%mod+tmp.m[1][2]%mod)%mod;
                    a = A,b = B;
                }
               
            }
            if(!rt) cout<<b<<endl;
        }
    }
}
发布了589 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_43408238/article/details/104159794