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
*/