hdu 1588(Fibonacci矩阵求和)

  题目的大意就是求等差数列对应的Fibonacci数值的和,容易知道Fibonacci对应的矩阵为[1,1,1,0],因为题目中f[0]=0,f[1]=1,所以推出最后结果f[n]=(A^n-1).a,所以 f(g(i))= f(k*i+b)= (A^(k*i+b-1)).a,i从 0取到 n-1,取出公因式 A^(b-1)(因为矩阵满足分配率),然后所求结果可化为 A^(b-1) * (A^0 + A^k + A^2k +....+ A^(n-1)k),化到这里后难点就是求和了,一开始我尝试暴力求和(每个A^k可以用快速幂求出,logn级别),即O(n)的做法,结果TLE了,预料之中,这时我竟傻乎乎地套用等比数列求和公式,即(A^nk -A^0) /(A^k -E),按比例放大再相减是没错,问题是不是简单的相除……总之思路应该是错的了,后来看别人的博客后才知道原来可以用二分来求和的,即 A^0 + A^k + A^2k +....+ A^(n-1)k = (A^0 + A^k + A^2k +...+ A^(n/2-1)k) *(E + A^(n/2)k),递归来求和,处理好 n的奇偶性即可,但我还是调试了好久,就因为在一些细节问题上出错却检查不出来,下面附上代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 using namespace std;
 5 typedef long long LL;
 6 LL mod= 1000000007;        //初不初始化都没问题,只是为了防止忘记读入时产生的异常退出
 7
 8 struct matrix{
 9     LL a,b,c,d;
10     matrix(LL a=0, LL b=0, LL c=0, LL d=0): a(a),b(b),c(c),d(d) {}
11     matrix operator +(const matrix &m2){
12         return matrix((a+m2.a)%mod,(b+m2.b)%mod,(c+m2.c)%mod,(d+m2.d)%mod);
13     }
14     matrix operator *(const matrix &m2){
15         return matrix((a*m2.a%mod+b*m2.c%mod)%mod, (a*m2.b%mod+b*m2.d%mod)%mod, (c*m2.a%mod+d*m2.c%mod)%mod, (c*m2.b%mod+d*m2.d%mod)%mod);
16     }
17     //一开始等比数列求和的思路要用到除法,后来才发现是错的,不过也不删了,就放在这吧
18     matrix operator /(const matrix &m2){
19         //二维求逆很好求的
20         matrix inv= matrix(m2.d,-m2.b,-m2.c,m2.a);
21         LL tmp= m2.a*m2.d-m2.b*m2.c;
22         return matrix((a*inv.a/tmp%mod+b*inv.c/tmp%mod)%mod, (a*inv.b/tmp%mod+b*inv.d/tmp%mod)%mod, (c*inv.a/tmp%mod+d*inv.c/tmp%mod)%mod, (c*inv.b/tmp%mod+d*inv.d/tmp%mod)%mod);
23     }
24 };
25 // A为 Fibonacci矩阵,E为单位矩阵,设为全局变量更方便一些
26 matrix A(1,1,1,0),E(1,0,0,1);
27
28 //简单的快速幂
29 matrix quick_mod(matrix m, LL b){
30     if(b==-1)    return matrix(0,1,1,-1);
31     //若指数为-1,返回矩阵 A^-1,相当于A^1的逆(算了好久T.T)
32     matrix res(E);        //res一开始为单位矩阵
33     while(b){
34         if(b&1)      res= res*m;
35         m= m*m;
36         b>>=1;
37     }
38     return res;
39 }
40
41 //二分法计算 A^0 + A^k + A^2k +....+ A^(n-1)k 的和
42 //即 sum =(A^0 + A^k + A^2k +...+ A^(n/2-1)k) *(E + A^(n/2)k),分治的思想
43 matrix quick_sum(LL k, LL n){
44     if(n==1)    return E;    //若 n为1,即计算 A^0,此时返回的是 E!而不是 A!一开始没想到错在这里,卡了好久 T.T
45     if(n%2==0)    return quick_sum(k,n/2)*(E+quick_mod(A,(n/2)*k));
46     //else    return quick_sum(k,(n-1)/2)*(E+quick_mod(A,((n-1)/2)*k))*quick_mod(A,(n-1)*k);
47     else    return quick_sum(k,n-1) + quick_mod(A,(n-1)*k);
48     //这样的写法比起上一行的虽然会多一次调用函数的开销,但可读性增强,代码逻辑更清晰
49 }
50
51 int main()
52 {
53     //freopen("1588in.txt","r",stdin);
54     LL k,b,n;
55     while(~scanf("%I64d%I64d%I64d%I64d",&k,&b,&n,&mod)){
56         //最后的结果就是 A^b-1 *(A0 + A^k + A^2k +...+ A(n-1)k) 的 a
57         matrix ans= quick_mod(A,b-1) * quick_sum(k,n);
58         printf("%I64d\n",ans.a);
59     }
60     return 0;
61 }
时间: 2024-12-15 06:56:48

hdu 1588(Fibonacci矩阵求和)的相关文章

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

hdu 1588 Gauss Fibonacci(等比矩阵二分求和)

题目链接:hdu 1588 Gauss Fibonacci 题意: g(i)=k*i+b; f(0)=0f(1)=1f(n)=f(n-1)+f(n-2) (n>=2) 让你求:sum(f(g(i)))for 0<=i<n 题解: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,0,1}, (花括号表示矩阵...) // 也就是fib数的变化矩阵,F(x) = (A^x) * {1,0} = F(b) + (

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

hdu 1588 Gauss Fibonacci(矩阵快速幂)

Gauss Fibonacci Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2090    Accepted Submission(s): 903 Problem Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r

hdu 1588 Gauss Fibonacci(矩阵嵌矩阵)

题目大意: 求出斐波那契中的 第 k*i+b 项的和. 思路分析: 定义斐波那契数列的矩阵 f(n)为斐波那契第n项 F(n) = f(n+1) f(n) 那么可以知道矩阵 A = 1 1 1  0 使得 F(n) = A * F(n+1) 然后我们化简最后的答案 sum = F(b) +   F(K+b) +  F (2*k +b).... sum = F(b) +  A^k F(b)    +   A^2k F(b)..... sum = (E+A^k + A^2k.....)*F(b) 那

矩阵十题【三】 HDU 1588 Gauss Fibonacci

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1588 题目大意:先要知道一组斐波那契数列 i 0 1 2 3 4 5 6 7 f(i) 0 1 1 2 3 5 8 13 下面给你一组数: k,b,n,M 现在知道一组公式g(i)=k*i+b:(i=0,1,2,3...n-1) 让你求出 f(g(i)) 的总和(i=01,2,3,...,n-1),比如给出的数据是2 1 4 100 2*0+1=1   f(1)=1 2*1+1=3   f(3)=2

HDU - 1588 Gauss Fibonacci (矩阵快速幂+二分求等比数列和)

Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. " How good an opportunity that Gardon can not give up! The "Prob

HDU 1588 Gauss Fibonacci(矩阵快速幂)

题目地址:HDU 1588 用于构造斐波那契的矩阵为 1,1 1,0 设这个矩阵为A. sum=f(b)+f(k+b)+f(2*k+b)+f(3*k+b)+........+f((n-1)*k+b) <=>sum=A^b+A^(k+b)+A^(2*k+b)+A^(3*k+b)+........+A^((n-1)*k+b) <=>sum=A^b+A^b*(A^k+A^2*k+A^3*k+.......+A^((n-1)*k))(1) 设矩阵B为A^k; 那么(1)式为 sum=A^b

hdu 3326 Another kind of Fibonacci (矩阵构造)

题目大意: 描述了另外一种斐波那契 F[n] = x*F[n-1] + y*F[n-2]; 求segma(F[i]^2): 思路分析: 构造矩阵的详细 请戳我 构造矩阵可以得到 中间矩阵为 1 1 0 0 0 x^2      y^2   2*x*y 0 1 0 0 0 x 0 y #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <