题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3936
题目的意思是,p[i] =F[4 * i - 1],(F为斐波那契数列,F1 = 1,F2 = 1)。。求p[L] ~ p[R]的和。(包括p[L] , p[R])。。。。。每次询问,L,R(L,R均小于10^12)。。。最多询问10^4次。。。
推个公式吧。。。正确的公式是矩阵快速幂的前提。。。所以就开始推了。。。
设Si 为p[1] ~ p[i] 的和。。Si = Si-1 + F(4 *1 - 1)。。。这么容易就出来了。。。毫无违和感啊。。。
那就来推状态转移矩阵吧。。。。
初始状态矩阵。。
(Si-1, F4i - 2, F4i - 3)
A = {
1 0 0
1 1 1
1 1 0
};
转移状态(Si,F4i-1,F4i -2)。。。
好easy。。。很happy的开始写程序。。。各种条,就是不对。。。纳闷了。。。
后来又推了一下 。。。状态方程错了。。。。。。好吧。。
上述公式错误。。LZ你逗我??
后来再推状态转移矩阵。。。
我们发现。。。p的推导对于F是不连续的。。。。每个p相对于F相隔4个。。。那么我们的状态矩阵可以涉及到相邻的每个p。。。也即是相邻的每4个F。。这样说好像比较抽象。。。那就举个例子吧。。
比如第一个状态到第二个状态。。。
(S1,F6,F5,F4,F3)->(S2,F10,F9,F8,F7)
当然这不是唯一的状态转移方式。。。
以上面的例子来推导状态转移矩阵。。。
A = {
1 5 3 2 1
1 3 2 1 1
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
};
比较有意思。。。当然,不同的转移方式会有不同的状态转移矩阵。。。。
这样就很可以了。。。矩阵快速幂求。。。。。
Code:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define LL long long
const int N = 10;
const LL mod = 1000000007;
struct Matrix
{
int n, m;
LL a[N][N];
void CLR(){
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++)
a[i][j] = 0;
}
}
void Unit(){
for(int i = 1; i <= n; i ++){
a[i][i] = 1;
}
}
};
Matrix operator *(Matrix a, Matrix b)
{
Matrix ans;
ans.n = a.n; ans.m = b.m;
ans.CLR();
for(int i = 1; i <= a.n; i ++){
for(int k = 1; k <= b.m; k ++){
if(a.a[i][k])
for(int j = 1; j <= b.n; j ++)
ans.a[i][j] = (ans.a[i][j] + a.a[i][k] * b.a[k][j]) % mod;
}
}
return ans;
}
Matrix power(Matrix ans, Matrix A, LL k)
{
if(k < 0) {
ans.a[1][1] = 0;
return ans;
}
while(k){
if(k & 1) ans = ans * A;
A = A * A;
k = k >> 1;
}
return ans;
}
int main()
{
// freopen("1.txt", "r", stdin);
// freopen("2.txt", "w", stdout);
int q;
cin >> q;
Matrix A;
A.n = 5;A.m = 5;
A.CLR();
A.a[1][1] = 1;
A.a[2][1] = 1; A.a[2][2] = 5; A.a[2][3] = 3; A.a[2][4] = 2; A.a[2][5] = 1;
A.a[3][1] = 1; A.a[3][2] = 3; A.a[3][3] = 2; A.a[3][4] = 1; A.a[3][5] = 1;
while(q --){
LL l, r;
cin >> l >> r;
Matrix ans;
ans.n = 1; ans.m = 5;
ans.CLR();
ans.a[1][1] = 2; ans.a[1][2] = 8; ans.a[1][3] = 5; ans.a[1][4] = 3; ans.a[1][5] = 2;
LL xans = power(ans, A, r - 1).a[1][1] - power(ans, A, l - 1 - 1).a[1][1];
printf("%I64d\n",(xans % mod + mod) % mod);
}
return 0;
}
然后就是被卡了那么一小会儿。。。(一个上午T.T)。。
最后发现。。。。取模那可能为负。。。表示 。。。。无语了那么一会儿。。好吧。。还是自己比较嫩。。。