UVA - 10870 Recurrences

Consider recurrent functions of the following form:
f(n) = a1f(n − 1) + a2f(n − 2) + a3f(n − 3) + . . . + adf(n − d), for n > d,
where a1, a2, . . . , ad are arbitrary constants.
A famous example is the Fibonacci sequence, defined as: f(1) = 1, f(2) = 1, f(n) = f(n − 1) +
f(n − 2). Here d = 2, a1 = 1, a2 = 1.
Every such function is completely described by specifying d (which is called the order of recurrence),
values of d coefficients: a1, a2, . . . , ad, and values of f(1), f(2), . . . , f(d). You’ll be given these numbers,
and two integers n and m. Your program’s job is to compute f(n) modulo m.
Input
Input file contains several test cases. Each test case begins with three integers: d, n, m, followed by
two sets of d non-negative integers. The first set contains coefficients: a1, a2, . . . , ad. The second set
gives values of f(1), f(2), . . . , f(d).
You can assume that: 1 ≤ d ≤ 15, 1 ≤ n ≤ 2
31 − 1, 1 ≤ m ≤ 46340. All numbers in the input will
fit in signed 32-bit integer.
Input is terminated by line containing three zeroes instead of d, n, m. Two consecutive test cases
are separated by a blank line.
Output
For each test case, print the value of f(n)( mod m) on a separate line. It must be a non-negative integer,
less than m.
Sample Input
1 1 100
2
1
2 10 100
1 1
1 1
3 2147483647 12345
12345678 0 12345

1 2 3


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#define max_ 200010
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

struct mat
{
    ll num[20][20];
    int n;
};
int m,n,k,d;
int f[20];
mat mul(struct mat a,struct mat b)
{
    struct mat ans;
    ans.n=a.n;
    memset(ans.num,0,sizeof(ans.num));
    for(int i=1;i<=a.n;i++)
    {
        for(int j=1;j<=a.n;j++)
        {
            for(int k=1;k<=a.n;k++)
            {
                ans.num[i][j]+=(a.num[i][k]*b.num[k][j])%m;
                ans.num[i][j]%=m;
            }
        }
    }
    return ans;
}
void show(struct mat a)
{
    printf("%d\n",a.n);
    for(int i=1;i<=a.n;i++)
    {
        for(int j=1;j<=a.n;j++)
        {
            printf("%d ",a.num[i][j]);
        }
        printf("\n" );
    }
}
int fpow(struct mat a,int k)
{
    struct mat ans,tmp=a;
    ans.n=a.n;
    memset(ans.num,0,sizeof(ans.num));
    for(int i=1;i<=a.n;i++)
        ans.num[i][i]=1;

    while(k!=0)
    {
        if(k&1)
            ans=mul(ans,tmp);
        tmp=mul(tmp,tmp);
        k/=2;
    }
    int sum=0;
    for(int i=1;i<=d;i++)
    {
        sum+=(ans.num[1][i]*f[d-i+1])%m;
    }
    return (sum%m);
}
int main(int argc, char const *argv[]) {
    while(cin>>d>>n>>m)
    {
        if(d==0&&n==0&&m==0)
        break;
        mat a;
        a.n=d;
        memset(a.num,0,sizeof(a.num));
        for(int i=1;i<=d;i++)
        {
            cin>>a.num[1][i];
            a.num[1][i]%=m;
            if(i!=d)
            a.num[i+1][i]=1;
        }
        for(int i=1;i<=d;i++)
        {
            cin>>f[i];
            f[i]%=m;
        }
        if(n<=d)
        {
            printf("%d\n",f[n]%m);
            continue;
        }
        printf("%d\n",fpow(a,n-d) );
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值