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 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 "Problem GF" told by Angel is actually "Gauss Fibonacci".

As we know ,Gauss is the famous mathematician who worked out the sum from 1 to 100 very quickly, and Fibonacci is the crazy man who invented some numbers.

Arithmetic progression:

g(i)=k*i+b;

We assume k and b are both non-nagetive integers.

Fibonacci Numbers:

f(0)=0

f(1)=1

f(n)=f(n-1)+f(n-2) (n>=2)

The Gauss Fibonacci problem is described as follows:

Given k,b,n ,calculate the sum of every f(g(i)) for 0<=i<n

The answer may be very large, so you should divide this answer by M and just output the remainder instead.

Input

The input contains serveral lines. For each line there are four non-nagetive integers: k,b,n,M

Each of them will not exceed 1,000,000,000.

Output

For each line input, out the value described above.

Sample Input

2 1 4 100
2 0 4 100

Sample Output

21
12

Author

DYGG

Source

HDU “Valentines
Day” Open Programming Contest 2007-02-14

题解及代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int mod=1e9;
struct mat
{
    __int64 t[4][4];
    void set()
    {
        memset(t,0,sizeof(t));
    }
} a,b,c;

mat multiple(mat a,mat b,int n,int p)
{
    int i,j,k;
    mat temp;
    temp.set();
    for(i=0; i<n; i++)
        for(j=0; j<n; j++)
        {
            if(a.t[i][j]!=0)
                for(k=0; k<n; k++)
                    temp.t[i][k]=(temp.t[i][k]+a.t[i][j]*b.t[j][k]+p)%p;
        }
    return temp;
}

mat quick_mod(mat b,int n,int m,int p)
{
    mat t;
    t.set();
    for(int i=0;i<n;i++) t.t[i][i]=1;
    while(m)
    {
        if(m&1)
        {
            t=multiple(t,b,n,p);
        }
        m>>=1;
        b=multiple(b,b,n,p);
    }
    return t;
}

void init1()
{
   b.set();
   b.t[0][1]=1;
   b.t[1][0]=1;
   b.t[1][1]=1;
}
void init2()
{
    b.t[0][2]=1;
    b.t[1][3]=1;
    b.t[2][2]=1;
    b.t[3][3]=1;
}
int main()
{
    int  _k,_b,_n,M;
    while(cin>>_k>>_b>>_n>>M)
    {
        init1();
        a=quick_mod(b,2,_b,M);
        init1();
        b=quick_mod(b,2,_k,M);
        init2();
        c=quick_mod(b,4,_n,M);

        __int64 ans=0;

        b.t[0][0]=c.t[0][2];
        b.t[0][1]=c.t[0][3];
        b.t[1][0]=c.t[1][2];
        b.t[1][1]=c.t[1][3];

        c=multiple(a,b,2,M);

        ans=c.t[1][0];
        cout<<ans<<endl;
    }
    return 0;
}
/*
F为斐波那契数列:F[0]=0,F[1]=1,F[n]=F[n-1]+F[n-2];
g为一个函数,g(i)=k*i+b;
S[n]=∑F[g(i)]=F[b]+F[k+b]+F[k*2+b]+……+F[k*(n-1)+b]
我们设A为斐波那契数列的初始矩阵,B为转换矩阵
那么S[n]=A*B^b+A*B^(k+b)+A*B^(k*2+b)+……+A*B^((n-1)*k+b)
=A*B^b*(I+B^k+B^(2*k)+……+B^((n-1)*k))
那么我们这里只需要求出A,B^b和I+B^k+B^(2*k)+……+B^((n-1)*k)就可以了
当然前两个比较好求,关键是后面这个,首先我们可以先求出B^k=C
然后在构造一个4*4的矩阵来求和
|C I| 其二次方是|C^2 I+C| 三次方|C^3 I+C+C^2| …… 这样我们就能求出和了。
|0 I|          |0     I|       |0         I|
*/

hdu 1588 Gauss Fibonacci(矩阵快速幂),布布扣,bubuko.com

时间: 2024-10-27 09:24:36

hdu 1588 Gauss Fibonacci(矩阵快速幂)的相关文章

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 1588 Gauss Fibonacci 矩阵

首先fib数列可以很随意的推出来矩阵解法,然后这里就是要处理一个关于矩阵的等比数列求和的问题,这里有一个logn的解法,类似与这样 A^0+A^1+A^2+A^3 = A^0 + A^1 + A^2 * (A^0 + A^1) 处理就好了. #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <

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 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(矩阵高速幂+二分等比序列求和) 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

题目链接: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(等比矩阵二分求和)

题目链接: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(矩阵嵌矩阵)

题目大意: 求出斐波那契中的 第 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 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 2254 奥运 题意: 中问题不解释. 分析: 根据floyd的算法,矩阵的k次方表示这个矩阵走了k步. 所以k天后就算矩阵的k次方. 这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和. 所以就是二分等比序列求和上场的时候了. 跟HDU 1588 Gauss Fibonacci的算法一样. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * B