hdu1757 A Simple Math Problem

本文介绍了一种解决特定递推数列问题的方法——递归矩阵快速幂算法,并提供了完整的C++代码实现。该方法适用于当数列项依赖于前几项且系数固定的场景,通过矩阵快速幂可以有效地计算出第n项对m取模的结果。
Problem Description
Lele now is thinking about a simple function f(x).

If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .

Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
 

 

Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
 

 

Output
For each case, output f(k) % m in one line.
 

 

Sample Input
10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
 

 

Sample Output
45 104
/*
裸题
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 30;
ll sz,mod,f[maxn],a[maxn],ans[maxn];
struct mtx{
    ll v[maxn][maxn];
    void clear(){
        memset(v,0,sizeof(v));
    }
    mtx mul(mtx A,mtx B){
        mtx C;
        C.clear();
        for(int i = 1;i <= sz;i++){
            for(int j = 1;j <= sz;j++){
                for(int k = 1;k <= sz;k++){
                    C.v[i][j] = (C.v[i][j] + A.v[i][k]*B.v[k][j]) % mod;
                }
            }
        }
        return C;
    }
    mtx pow(mtx A,int n){
        mtx R;
        R.clear();
        for(int i = 1;i <= sz;i++) R.v[i][i] = 1;
        while(n){
            if(n&1) R = R.mul(R,A);
            n >>= 1;
            A = A.mul(A,A);
        }
        return R;
    }
    void get_tr(mtx A){
        for(int i = 1;i <= sz;i++){
            for(int j = 1;j <= sz;j++){
                ans[j] = (ans[j] + f[i]*A.v[i][j]) % mod;
            }
        }
    }
};
int main(){
    ll d,n,m;
   while(scanf("%I64d%I64d",&n,&m) == 2) {
       d = 10;
       mtx A;
    for(int i = 1; i <= d; i++) { cin >> a[i]; a[i] %= m; }
    for(int i = d; i >= 1; i--) { f[i] = d-i; f[i] %= m; }
    if(n < 10){
        cout<<n<<endl;
        continue;
    }
    n++;
    A.clear();
    memset(ans,0,sizeof(ans));
    for(int i = 1; i <= d; i++) A.v[i][1] = a[i];
    for(int i = 2; i <= d; i++) A.v[i-1][i] = 1;

    sz = d;
    mod = m;
    A = A.pow(A,n-d);
    A.get_tr(A);
    cout << ans[1] << endl;
  }
    return 0;
}

 

转载于:https://www.cnblogs.com/hyfer/p/5974827.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值