zoj 3772 Calculate the Function monthly 14th

来源:互联网 发布:电子秤数据倒显 编辑:程序博客网 时间:2024/05/29 09:43
题意:
给一个数组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 取模


方法一:复杂度O(n+m*log(MOD))
看到递推公式,不难想到递推公式
[F[n+2]] = [1 A[n+2]] * [F[n+1]] = ... = [1 A[n+2]] * [1 A[n+2]] * ... * [1 A[3]] * [F[2]][F[n+1]]   [1   0   ]   [F[n]  ]         [1   0   ]   [1   0   ]         [1   0 ]   [F[1]]

matrix[n] =  [1 A[n]] * [1 A[n-1]] * ... * [1 A[3]]             [1   0 ]   [1   0   ]         [1   0 ]

其中n>=3,matrix[n]是一个2*2的矩阵

[F[n]  ] = matrix[n] * [F[2]][F[n-1]]               [F[1]]
其中n>=3
当我们给一个查询L,R时,
[F[R]  ] = matrix[R] * [f[2]][F[R-1]]               [f[1]][F[L+1]] = matrix[L+1] * [f[2]][F[L]  ]                 [f[1]]
要求2*2的矩阵[X]使得,
[f[R]  ] = [X] * [f[L+1]][f[R-1]]         [f[L]  ]
等价于
matrix[R] * [f[2]] = [X] * matrix[L+1] * [f[2]]            [f[1]]                       [f[1]]
所以应该是 matrix[R] = [X] * matrix[L+1]
这里解矩阵[X]有两种方法:
(1)建立二元同余方程组(由于每次取模,所以是同余方程组而不是方程组)
(2)[X] = matrix[R] * matrix[L+1](-1),求逆再相乘
对于(1),可以用用扩展欧几里得解出(写出来有BUG。。。)
对于(2),2*2矩阵的逆:
[a b]-1 = 1/(ad-bc) * [d -b][c d]                 [-c a]
然而,模运算不支持除法,但是,除以一个数x在MOD下等价于乘以逆元x^(MOD-2)
(写出来很快。。)


方法二:O(nlog(n)+mlog(n))
线段树的方法,记
M[n] = [1 A[n]]       [1   0 ]
显然,
[F[R]  ] = M[R] * ... * M[L+2] * [F[L+1]][F[R-1]]                         [F[L]  ]
为了方便求出M[R] * ... * M[L+2],可以建立线段树
0 0
原创粉丝点击