UVA - 10870 Recurrences (矩陣快速冪)

Time Limit: 3000MS     64bit IO Format: %lld & %llu

 Status uDebug

Description

Download as PDF

題意:

考慮線性遞推關係f(n)=a1*f(n-1)+a2*f(n-2)+a3*f(n-3)+...+ad*f(n-d),給你三個整數n,m,d 與數組a與f,讓你計算f(n)%m。

分析:矩陣快速冪模板題。


#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
const long long N=1e5+5;
long long mod=1e9;
const double PI=acos(-1.0);
typedef long long ll;

typedef struct {
    int mat[16][16];
}Mat;

int n,d,m;

Mat multi(Mat a,Mat b) {
    Mat c;
    memset(c.mat, 0, sizeof(c.mat));
    for (int i=1; i<=d; i++) {
        for (int j=1; j<=d; j++) {
            for (int k=1; k<=d; k++) {
                c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
            }
        }
    }
    return c;
}

Mat qui(Mat a,ll b) {
    Mat c;
    memset(c.mat, 0, sizeof(c.mat));
    for (int i=1; i<=d; i++) {
        c.mat[i][i]=1;
    }
    while (b) {
        if (b&1) {
            c=multi(c, a);
        }
        a=multi(a, a);
        b>>=1;
    }
    return c;
}

int main() {
    int a[16],f[16];
    Mat A;
    while (cin>>d>>n>>m&&d) {
        mod=m;
        for (int i=1; i<=d; i++) {
            scanf("%d",&a[i]);
            a[i]%=mod;
        }
        for (int i=1; i<=d; i++) {
            scanf("%d",&f[i]);
            f[i]%=mod;
        }
        if (n<=d) {
            printf("%d\n",f[n]);
            continue;
        }
        
        memset(A.mat, 0, sizeof(A.mat));
        for (int i=2; i<=d; i++) {
            A.mat[i-1][i]=1;
        }
        for (int i=1; i<=d; i++) {
            A.mat[d][i]=a[d-i+1];
        }
        A=qui(A, n-1);
        ll ans=0;
        for (int i=1; i<=d; i++) {
            ans+=f[i]*A.mat[1][i];
            ans%=mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章