HDU1757 A Simple Math Problem【矩阵快速幂】

A Simple Math Problem

http://acm.hdu.edu.cn/showproblem.php?pid=1757

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7162    Accepted Submission(s): 4375


 

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

Author

linle

 

Source

2007省赛集训队练习赛(6)_linle专场

题意

x<10时 f(x) = x.
x>=10时  f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10)

给定k和m求f(k)%m

思路

由于k比较大,因此需使用矩阵快速幂。

C++代码

#include<iostream>
#include<vector>
#include<cstdio>

using namespace std;

typedef long long ll;
typedef vector<ll>vec;
typedef vector<vec>mat;

ll k,m;

mat mul(const mat &a,const mat &b)
{
    mat c(a.size(),vec(b[0].size()));
    for(int i=0;i<a.size();i++)
        for(int j=0;j<b[0].size();j++)
            for(int k=0;k<a[0].size();k++)
                c[i][j]=(c[i][j]+a[i][k]*b[k][j])%m;
    return c;
}

mat qpow(mat x,ll n)
{
    mat res(x.size(),vec(x.size()));
    for(int i=0;i<res.size();i++) res[i][i]=1;
    while(n)
    {
        if(n&1) res=mul(res,x);
        x=mul(x,x);
        n>>=1;
    }
    return res;
}

int a[10];

ll solve()
{
    if(k<10) return k%m;

    mat res(10,vec(1));

    for(int i=0;i<10;i++) res[9-i][0]=i%m;

    mat temp(10,vec(10));
    for(int i=0;i<10;i++)
    {
        temp[0][i]=a[i];
        if(i<9) temp[i+1][i]=1;
    }
    temp=qpow(temp,k-9);
    res=mul(temp,res);
    return res[0][0];
}

int main()
{
    while(~scanf("%lld%lld",&k,&m))
    {
        for(int i=0;i<10;i++) scanf("%d",&a[i]);
        printf("%lld\n",solve());
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值