ZOJ3772 矩阵+快速幂+逆元

ZOJ3772 矩阵+快速幂+逆元

挺有趣的一道题。。。

题意:

给一个数组A[1,2,...,n]和m个查询l,r; 对于每一个查询,

F[l] = A[l] ;   F[l+1] = A[l+1]

F[x] = F[x-1] + A[x]*F[x-2], x >= l+2

求F[r]。

1 <= A[i] <= 10^9; 1 <= n,m <=10^5

每一步骤均对 MOD = 10^9+7 取模

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<deque>
#include<bitset>
#define ll long long
using namespace std;
#define N 110000
#define MOD 1000000007
struct matrix
{
    ll A11,A12,A21,A22;//2*2矩阵的四个元素
}M_desc[N],M_ni_asc[N];//见上面说明
ll A[N];
matrix mul_matrix(matrix aa,matrix bb)
{
    matrix cc;
    cc.A11=((aa.A11*bb.A11)%MOD+(aa.A12*bb.A21)%MOD)%MOD;
    cc.A12=((aa.A11*bb.A12)%MOD+(aa.A12*bb.A22)%MOD)%MOD;
    cc.A21=((aa.A21*bb.A11)%MOD+(aa.A22*bb.A21)%MOD)%MOD;
    cc.A22=((aa.A21*bb.A12)%MOD+(aa.A22*bb.A22)%MOD)%MOD;
    return cc;
}
ll pow_mod(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2==1) ans=(ans*a)%MOD;
        a=(a*a)%MOD;
        b/=2;
    }
    return ans%MOD;
}
void init(int n)
{
    memset(M_desc,0,sizeof(M_desc));
    memset(M_ni_asc,0,sizeof(M_ni_asc));
    for(int i=1;i<=n;i++)
    {
        M_desc[i].A11=1;
        M_desc[i].A12=A[i];
        M_desc[i].A21=1;
        M_desc[i].A22=0;
        M_ni_asc[i].A11=0;
        M_ni_asc[i].A12=1;
        M_ni_asc[i].A21=pow_mod(A[i],MOD-2)%MOD;
        M_ni_asc[i].A22=((MOD-1)*pow_mod(A[i],MOD-2))%MOD;
    }
    for(int i=2;i<=n;i++)
    {
        M_desc[i]=mul_matrix(M_desc[i],M_desc[i-1]);
        M_ni_asc[i]=mul_matrix(M_ni_asc[i-1],M_ni_asc[i]);
    }
}
int main()
{
    int t,n,m;
    int i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&A[i]);
        }
        init(n);
        while(m--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            if(r<=l+1)
            {
                printf("%lld\n",A[r]);
                continue;
            }
            matrix now=mul_matrix(M_desc[r],M_ni_asc[l+1]);
            ll get=((now.A11*A[l+1])%MOD+(now.A12*A[l])%MOD)%MOD;
            printf("%lld\n",get);
        }
    }
}
/*
input:
1
4 7
1 2 3 4
1 1
1 2
1 3
1 4
2 4
3 4
4 4
output:
1
2
5
13
11
4
4
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值