hdoj 1757 A Simple Math Problem 【矩阵快速幂】

A Simple Math Problem

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


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专场
 
思路:
 
            这一道题其实不难,但是当你不知道矩阵相乘满足结合律的时候,你就非常容易出错!所以千万要记住,矩阵相乘满足结合律!每次计算的时候,我们都要用一个输入的列矩阵左乘一个方阵这样会得到一个列矩阵!但是当你用两个方阵相乘的时候,却得到一个方阵,,这样不同种类的矩阵相乘的时候,我们很容易出错,但是当你仔细一想,我们可以先算方阵的乘积,最后乘以列矩阵,这样,这个矩阵乘法的计算就很容易了!具体看代码!
 
代码:
 
//这一道题其实不难,但是当你不知道矩阵相乘满足结合律的时候,你就非常容易出错!所以千万要记住,矩阵相乘满足结合律!
//每次计算的时候,我们都要用一个输入的列矩阵左乘一个方阵这样会得到一个列矩阵!但是当你用两个方阵相乘的时候,却得到一个方阵,
//,这样不同种类的矩阵相乘的时候,我们很容易出错,但是当你仔细一想,我们可以先算方阵的乘积,最后乘以列矩阵,这样,这个矩阵乘法的计算
//就很容易了!具体看代码! 
#include 
#include 
#include 
using namespace std;
int k,m;
struct Maxtri
{
    int r,c;
    int a[15][15];
};
Maxtri ori,res;
void init()
{
    memset(res.a,0,sizeof(res.a));
    for(int i=1;i<=10;i++)
        res.a[i][i]=1;
    for(int i=2;i<=10;i++)
        for(int j=1;j<=10;j++)
        {
            if(i-1!=j)
                ori.a[i][j]=0;
            else
                ori.a[i][j]=1;
        }
}
Maxtri maxtri(Maxtri x,Maxtri y)
{
    Maxtri z;
    memset(z.a,0,sizeof(z.a));
    for(int i=1;i<=10;i++)
    {
        for(int k=1;k<=10;k++)
        {
            if(x.a[i][k]==0)    continue;
            for(int j=1;j<=10;j++)
                z.a[i][j]=(z.a[i][j]+(x.a[i][k]*y.a[k][j])%m)%m;//这一点取模一定要注意,错了n遍 
        }
    }
    return z;
}
void maxtri_mod(int n)
{
    while(n)
    {
        if(n%2!=0)
            res=maxtri(res,ori);
        ori=maxtri(ori,ori);
        n/=2;
    }
}
int main()
{
    while(scanf("%d%d",&k,&m)!=EOF)
    {
        for(int i=1;i<=10;i++)
            scanf("%d",&ori.a[1][i]);
        init();
        if(k<=9)
        {
            printf("%d\n",k%m);
            continue;
        }
        maxtri_mod(k-9);
        int sum=0;
        for(int i=1;i<=10;i++)
        {
            sum+=(res.a[1][i]*(10-i))%m;
            sum%=m;
        }
        printf("%d\n",sum%m);
    }
    return 0;
}

你可能感兴趣的:(矩阵快速幂)