1757 A Simple Math Problem(矩阵快速幂入门)

来源:互联网 发布:java基础电子书 编辑:程序博客网 时间:2024/06/05 14:53

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 99991 1 1 1 1 1 1 1 1 120 5001 0 1 0 1 0 1 0 1 0
 

Sample Output
45104
 

Author
linle
 

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


思路:这是第一个自己做出来的矩阵快速幂,还是有一点爽。
这道题目首先需要理清楚表达式的关系,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 longint 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;}



阅读全文
0 0
原创粉丝点击