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): 5025    Accepted Submission(s): 3037


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


思路:这是第一个自己做出来的矩阵快速幂,还是有一点爽。
这道题目首先需要理清楚表达式的关系,a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10),可以理解为单行矩阵与单列矩阵相乘,然后仔细思考后你会发现你每次相乘中f(x-1)......f(x-10)乘了n-9次,每次值得改变都是因为ai矩阵相乘。所以表达式变为(f(n)=a^n-9*F)

但是为了留下左边的结果,而不是单单的一个f(n)(因为每次的递归都是如左图形式,而不是ai矩阵乘单独的数f(n)),需要对ai矩阵进行一点修改,具体代码见注释。难点就是这么多,难得是这个公式向矩阵的转换。这是大牛口中的入门题,嗯,慢慢来。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 10
#define me(x) memset(x,0,sizeof(x))
#define ll long long
int mod;
struct mat//用结构体封装矩阵
{
    ll m[maxn][maxn];
}unit,temp,F;
///这三个矩阵分别为,单位矩阵、ai矩阵、F矩阵
void init()//初始化
{
    me(unit.m);
    me(temp.m);
    me(F.m);
    for(int i=0;i<10;i++)//单行
    {
        F.m[i][0]=9-i;
        unit.m[i][i]=1;
    }
    for(int i=0;i<9;i++)///只需要把第i+1行第i列修改就行
    {
        temp.m[i+1][i]=1;
    }
}

void print(mat a)//自己写的打印函数
{
    int i,j;
    for(i=0;i<10;i++)
    {
        for(j=0;j<10;j++)
            printf("%d ",a.m[i][j]);
        puts("");
    }
    puts("");
    return ;
}

mat operator*(mat a,mat b)//对*运算符重载为矩阵相乘
{
    mat p;
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<10;j++)
        {
            p.m[i][j]=0;
            for(int w=0;w<10;w++)
            {
                p.m[i][j]+=a.m[i][w]*b.m[w][j]%mod;
                p.m[i][j]%=mod;
            }
        }
    }
    return p;
}

ll pow(int k)//矩阵快速幂
{
    mat ans;
    ans=unit;
    //print(ans);
    //print(ans);
   //cout<<k<<endl;
   //int count=0;
    while(k)
    {
        //count++;
        if(k&1)
        {
            ans=ans*temp;
        }
        temp=temp*temp;
        k=k>>1;
    }
    //cout<<count<<endl;
    ans=ans*F; //print(ans);
    return ans.m[0][0]%mod;//因为ans[0][0]就是f(n);
}

int main()
{
    int k;
    while(scanf("%d %d",&k,&mod)!=EOF)
    {
        init();
        for(int i=0;i<10;i++)
        {
            scanf("%d",&temp.m[0][i]);
        }
        //cout<<endl<<endl;
        //print(temp);
        if(k<10) {printf("%d\n",k%mod);continue;}

        ll ans;
        //print(temp);
       // print(F);
        ans=pow(k-9);
       // ans=unit*F;
        cout<<ans%mod<<endl;
    }
    return 0;
}



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