hdu 1588(矩阵好题+递归求解等比数列)

Gauss Fibonacci

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3149    Accepted Submission(s): 1323

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

这个题要利用的东西挺多的。刚开始连斐波拉契的矩阵都弄错了,看来还是要加强训练!

把斐波那契数列转化为矩阵:
A={1 1}
  {1,0};

{f[n+1],f[n]}  
{f[n],f[n-1]} = A^n ;最后输出M.v[1][0]这就是构造斐波拉契数列的矩阵了。

这个题将式子化简之后我们可以得到

sum(f(g(n))) = A^(b)+A^(b+k)+...+A^(b+(n-1)*k) = A^b * (1+A^k+A^2k+...A^(n-1)k)

利用递归函数求解 A^k+A^2k+...A^(n-1)k 然后与 单位矩阵相加,最后还要判断 b是否为 0

很巧妙。

这里给出一个等比数列的求和公式.

LL cal(int p,int n){  ///这里是递归求解等比数列模板 1+p+p^2...+p^n
    if(n==0) return 1;
    if(n&1){//(1+p+p^2+....+p^(n/2))*(1+p^(n/2+1));
         return (1+pow_mod(p,n/2+1))*cal(p,n/2)%mod;
    }
    else { //(1+p+p^2+....+p^(n/2-1))*(1+p^(n/2+1))+p^(n/2);
         return (pow_mod(p,n/2)+(1+pow_mod(p,n/2+1))*cal(p,n/2-1))%mod;
    }
}
#include<stdio.h>
#include<iostream>
#include<string.h>
#include <stdlib.h>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long LL;
struct Martix{
    LL v[2][2];
}res;
LL k,b,n,M;

Martix mult(Martix a,Martix b){
    Martix temp;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            temp.v[i][j] = 0;
            for(int k=0;k<2;k++){
                temp.v[i][j] = (temp.v[i][j]+a.v[i][k]*b.v[k][j])%M;
            }
        }
    }
    return temp;
}

Martix add(Martix a,Martix b){
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            a.v[i][j]=(a.v[i][j]+b.v[i][j])%M;
        }
    }
    return a;
}
Martix pow_mod(Martix a,LL k){
    Martix ans;
    ans.v[0][0]=ans.v[1][1] = 1;
    ans.v[0][1]= ans.v[1][0]=0;
    while(k){
        if(k&1) ans = mult(ans,a);
        a=mult(a,a);
        k>>=1;
    }
    return ans;
}

Martix cal(Martix p,LL k) ///用二分法求矩阵和,递归实现 计算 a^1+a^2.....+a^p
{
    if(k==1)
        return p;
    else if(k&1)
        return add(cal(p,k-1),pow_mod(p,k));
    else
        return mult(cal(p,k>>1),add(pow_mod(p,k>>1),res));
}

int main(){

    Martix a,t;
    a.v[0][0] = a.v[0][1] = a.v[1][0] = 1; ///斐波拉契数列的特征值矩阵[1 1 1 0]
    a.v[1][1] = 0;
    t.v[0][0] = t.v[1][1] = 1; ///单位矩阵
    t.v[0][1] = t.v[1][0] = 0;
    while(scanf("%lld%lld%lld%lld",&k,&b,&n,&M)!=EOF){
        Martix M1 = pow_mod(a,k);
        res = t;
        res = add(t,cal(M1,n-1));
        if(b!=0){
            Martix M3 = pow_mod(a,b);
            res = mult(res,M3);
        }
        printf("%d\n",res.v[0][1]%M);
    }
    return 0;
}
时间: 2024-10-08 08:49:09

hdu 1588(矩阵好题+递归求解等比数列)的相关文章

矩阵十题【三】 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 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(矩阵快速幂)

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

矩阵十题【五】 VOJ1049 HDU 2371 Decode the Strings

题目链接:https://vijos.org/p/1049 题目大意:顺次给出m个置换,反复使用这m个置换对初始序列进行操作,问k次置换后的序列.m<=10, k<2^31. 首先将这m个置换"合并"起来(算出这m个置换的乘积),然后接下来我们需要执行这个置换k/m次(取整,若有余数则剩下几步模拟即可).注意任意一个置换都可以表示成矩阵的形式.例如,将1 2 3 4置换为3 1 2 4,相当于下面的矩阵乘法: 置换k/m次就相当于在前面乘以k/m个这样的矩阵.我们可以二分计

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 4920 Matrix multiplication(矩阵坑题)

http://acm.hdu.edu.cn/showproblem.php?pid=4920 被这道题虐了一下午,啥也不说了.继续矩阵吧. 超时就超在每步取余上,要放在最后取余,再者注意三个循环的次序. #include <stdio.h> #include <map> #include <set> #include <stack> #include <queue> #include <vector> #include <cma

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