hdu 1005

本文介绍了一种使用矩阵快速幂求解特定形式数列的方法。针对形如f(n)=(a*f(n-1)+b*f(n-2))mod7的数列,通过构建和操作2x2矩阵来高效计算f(n),适用于大规模数值计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目概述

给定一个数列f,该数列符合如下公式
f(1) = 1, f(2) = 1, f(n) = (a * f(n - 1) + b * f(n - 2)) mod 7
其中a,b,n已知,求f(n)的值

输入

每行三个数,a,b,n,其意义如上所示,输入以三个0结束并忽略该组数据

限制

1<=a,b<=1000;1<=n<=1e8;

输出

每行一个数,f(n)

样例输入

1 1 1
1 2 10
1 1 2
1 1 3
1 1 6
1 1 7
2 3 1
2 3 2
2 3 3
2 3 4
0 0 0

样例输出

1
5
1
2
1
6
1
1
5
6

讨论

考察斐波那契数列的矩阵求法,并且简单的扩展了一下,要注意的地方莫过于几个需要求模的地方,以及应当如何处理a,b在矩阵中的位置

题解状态

0MS,1728K,1611 B,C++

题解代码

#include<algorithm>  
#include<string.h>  
#include<stdio.h>  
#include<iostream>
#include<set>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f  
#define maxx(a,b) ((a)>(b)?(a):(b))  
#define minn(a,b) ((a)<(b)?(a):(b))  
#define MAXN 26
#define memset0(a) memset(a,0,sizeof(a))

struct matrix//2x2矩阵
{
    int a0[2], a1[2];//矩阵的四个数
    matrix()//默认构造二阶单位矩阵
    {
        a0[0] = 1;
        a0[1] = 0;
        a1[0] = 0;
        a1[1] = 1;
    }
    matrix(int a, int b, int c, int d)
    {
        a0[0] = a;
        a0[1] = b;
        a1[0] = c;
        a1[1] = d;
    }
    matrix operator*(matrix b)//矩阵乘法
    {
        matrix s;
        s.a0[0] = a0[0] * b.a0[0] + a0[1] * b.a1[0];
        s.a0[1] = a0[0] * b.a0[1] + a0[1] * b.a1[1];
        s.a1[0] = a1[0] * b.a0[0] + a1[1] * b.a1[0];
        s.a1[1] = a1[0] * b.a0[1] + a1[1] * b.a1[1];
        return s;
    }
    matrix operator%(int b)//矩阵模
    {
        matrix s;
        s.a0[0] = a0[0] % b;
        s.a0[1] = a0[1] % b;
        s.a1[0] = a1[0] % b;
        s.a1[1] = a1[1] % b;
        return s;
    }
};
matrix qpow(matrix a, int n, int mod)//矩阵快速幂
{
    if (!n)
        return matrix();
    else if (n == 1)
        return a%mod;
    else if (n % 2 == 1)
        return ((qpow(a*a%mod, n / 2, mod) % mod)*(a%mod)) % mod;
    else
        return qpow(a*a%mod, n / 2, mod) % mod;
}
int fun(int a, int b, int n)
{
    matrix s(1, 1, 1, 0);
    matrix c(a, 1, b, 0);
    c = qpow(c, n - 2, 7);
    return (s*c).a0[0]%7;//注意这里也需要求模
}
int main(void)
{
    //freopen("vs_cin.txt", "r", stdin);
    //freopen("vs_cout.txt", "w", stdout);

    int a, b, n;
    while (~scanf("%d%d%d", &a, &b, &n) && (a || b || n)) {//input
        if (n == 1 || n == 2)
            printf("1\n");//output//前两个数必然为1 若进行计算 则f(2)可能不为1而出错
        else
            printf("%d\n", fun(a, b, n));//output
    }
}

EOF

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值