zoukankan      html  css  js  c++  java
  • HDU6395 Sequence(矩阵快速幂+数论分块)

    题意:

    F(1)=A,F(2)=B,F(n)=C*F(n-2)+D*F(n-1)+P/n

    给定ABCDPn,求F(n) mod 1e9+7

    思路:

    P/n在一段n里是不变的,可以数论分块,再在每一段里用矩阵快速幂

    debug了一下午。。

    坑点:

    1.数论分块的写法要注意,已更新

    2.矩阵乘法在赋值回去的时候记得模一下

    3.矩阵相乘不可逆,注意看一下

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
    
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e6+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    void prt(ll b[4][4]){
        for(int i = 1; i <= 3; i++){
            for(int j = 1; j <= 3; j++){
                printf("%3I64d ", b[i][j]);
            }
            printf("
    ");
        }
        return;
    }
    void mtpl(ll a[4][4], ll b[4][4], ll s[4][4]){
        ll tmp[4][4];
        mem(tmp, 0);
        for(int i = 1; i <= 3; i++){
            for(int j = 1; j <= 3; j++){
                
                for(int k = 1; k <= 3; k++){
                    tmp[i][j] += (a[i][k]*b[k][j])%mod;
                }
            }
        }
        for(int i = 1; i <= 3; i++){
            for(int j = 1; j <= 3; j++){
                s[i][j] = tmp[i][j]%mod;
            }
        }
        return;
    }ll a, b, c, d, p, n;
    ll B[4][4];
    void fp(ll n, ll tmp){
        ll A[4][4];
        mem(A, 0);
        A[1][1] = d;
        A[1][2] = c;
        A[2][1] = 1;
        A[1][3] = tmp;
        A[3][3] = 1;
        //prt(A);
        while(n){
            if(n&1) mtpl(A,B,B);
            mtpl(A,A,A);
            n>>=1;
        }
        return;
    }
    int main() {
        int T;
        scanf("%d",&T);
        while(T--){
            
            scanf("%I64d %I64d %I64d %I64d %I64d %I64d", &a, &b, &c, &d, &p, &n);
            
            if(n==1){
                printf("%I64d
    ", a);
                continue;
            }
            if(n==2){
                printf("%I64d
    ", b);
                continue;
            }
            
            mem(B, 0);
            for(int i = 1; i <= 3; i++)B[i][i]=1;
            B[1][1] = b;
            B[2][1] = a;
            B[3][1] = 1;
            ll l , r;
            for(l = 3, r = 0; l <= n; l = r + 1){
                if(p/l) r = min(p, p/(p/l));
                else r = n;
                ll tmp = p/l;
                fp(r-l+1,tmp);
            }
            
    
            printf("%I64d
    ", B[1][1]);
        }
        return 0;
    }
    /*
    4
    1 2 1 2 5 3
    1 2 1 2 3 5
    1 2 3 4 7 4
    2 3 3 3 3 4
    
     */
  • 相关阅读:
    Java.Io 初步了解
    Java 对象序列化与反序列化
    Java
    Java
    Java
    实现文件拷贝
    Java
    Java 国际化标准程序实现
    【C#】分享带等待窗体的任务执行器一枚
    解决64位Windows2003程序字体很小的问题
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/9484799.html
Copyright © 2011-2022 走看看