题解:UVA10870 Recurrences

UVA10870 题解

题面

原题传送门

题意

考虑以下形式的递推函数:

\(f(n)=a_1f(n-1)+a_2f(n-2)+a_3f(n-3)+\cdots+a_df(n-d)\)(当 \(n>d\) 时)

其中 \(a_1,a_2,\cdots,a_d\) 是任意常数。

  • 递推的阶数 \(d\)(称为递推的阶数),
  • \(d\) 个系数 \(a_1,a_2,\cdots,a_d\)
  • 初始值 \(f(1),f(2),\cdots,f(d)\)

输入将给定这些数字,以及两个整数 \(n\)\(m\)。程序的任务是计算 \(f(n)\)\(m\) 取模的结果。

思路

这题是裸的矩阵加速。(应该没有蓝吧……)

首先我们有如下式子。

  • \(f_i=a_1\times f_{i-1}+a_2\times f_{i-2}+\cdots+a_d\times f_{i-d}\)
  • \(f_{i-1}=1\times f_{i-1}+0\times f_{i-2}+\cdots+0\times f_{i-d}\)
  • \(f_{i-2}=0\times f_{i-1}+1\times f_{i-2}+\cdots+0\times f_{i-d}\)
  • \(\cdots\)
  • \(f_{i-d+1}=0\times f_{i-1}+0\times f_{i-2}+\cdots+1\times f_{i-d+1}+0\times f_{i-d}\)

把这些式子化成矩阵。

\(\begin{bmatrix}f_i\\f_{i-1}\\\cdots\\f_{i-d+2}\\f_{i-d+1}\end{bmatrix}=\begin{bmatrix}a_1&a_2&\cdots&a_{d-1}&a_d\\1&0&\cdots&0&0\\0&1&\cdots&0&0\\&&\cdots\\0&0&\cdots&1&0\end{bmatrix}\times\begin{bmatrix}f_{i-1}\\f_{i-2}\\\cdots\\f_{i-d+1}\\f_{i-d}\end{bmatrix}\)

于是要是 \(n\leqslant d\) 的话直接输出 \(f_n\),否则我们就可以用矩阵快速幂加速。

\(\begin{bmatrix}f_i\\f_{n-1}\\\cdots\\f_{n-d+2}\\f_{n-d+1}\end{bmatrix}=\begin{bmatrix}a_1&a_2&\cdots&a_{d-1}&a_d\\1&0&\cdots&0&0\\0&1&\cdots&0&0\\&&\cdots\\0&0&\cdots&1&0\end{bmatrix}^{n-d}\times\begin{bmatrix}f_{d}\\f_{d-1}\\\cdots\\f_{2}\\f_{1}\end{bmatrix}\)

注意,在输入答案矩阵的时候是倒着输入的,不要搞错了。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
ll k,n,mod;
class matrix{
    public:
    ll g[25][25];
    matrix(){for(int i=0; i<k; i++) for(int j=0; j<k; j++)g[i][j]=0;}
    void clear(){for(int i=0; i<k; i++) for(int j=0; j<k; j++)g[i][j]=0;}
    void print(){for(int i=0; i<k; i++){for(int j=0; j<k; j++)cout<<g[i][j]<<' ';cout<<endl;}}
    matrix& operator = (const matrix& x){for(int i=0; i<k; i++) for(int j=0; j<k; j++) g[i][j]=x.g[i][j];return *this;}
    matrix operator * (const matrix& x){matrix c;for(int i=0; i<k; i++) for(int j=0; j<k; j++) for(int l=0; l<k; l++) (c.g[i][j]+=g[i][l]*x.g[l][j]%mod)%=mod;return c;}
    matrix operator ^ (const ll& x){matrix res,a=*this;ll b=x;for(int i=0; i<k; i++) res.g[i][i]=1;while(b){if(b&1)res=res*a;a=a*a;b>>=1;}return res;}
};
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
int main(){
    while(1){
        k=read();n=read();mod=read();
        if(!k&&!n&&!mod) return 0;
        matrix f,ans;
        for(int i=1; i<k; i++) f.g[i][i-1]=1;
        for(int i=0; i<k; i++) f.g[0][i]=read();
        for(int i=k-1; ~i; i--) ans.g[i][0]=read();
        if(n<=k){write(ans.g[k-n][0]%mod);putchar('\n');continue;}
        f=f^(n-k);ans=f*ans;
        write(ans.g[0][0]);putchar('\n');
    }
}
posted @ 2025-01-29 16:06  naroto2022  阅读(9)  评论(0)    收藏  举报