Additions HNUST 1713(矩阵快速幂模板 )

Ada is 5 years old, and she is learning additions. Her father writes some exercises for her.


1+11=?


2+22=?


3+33=?


“It is easy”, she writes the answer correctly. “Try to answer the following questions”,


 1+11+111=?


 2+22+222+2222=?


Ada scratches her head. “It’s too difficult”. 


So, help Ada to compute the value of equation a+aa+aaa+... which have n items. Since the answer may be quite large, you have to module it by an integer m.


输入
Input contains at most 1000 test cases. Each test case contains only one line.


Each line will contain three integers a, n and m. (1<=a<=9, 1<=n<231-1, 1<=m<=100007).   Process to end of file.


输出
For each test cases, output the value of (a+aa+aaa+... .)%m。


样例输入
1 1 13
1 2 13
1 3 13
2 2 13
2 3 13
样例输出
1
12
6
11

12

思路:刚开始看到这个题目想的是纯模拟,但是高达了2^31-1,所以不可以,后来队友告诉我,可以构造出来一个递推的式子

|1 10 1|  |fn-1|   |fn|
|0 10 1|  |xn-1|=|xn|
|0 0   1|   |a     |  |a|

|1 10 1|^n-1   |f1|   |fn|
|0 10 1|          |x1|=|xn|
|0  0  1|          |a     |  |a|

#include
using namespace std;
typedef long long ll;
/*1 10 1||fn-1|   |fn|
0 10 1||xn-1|=|xn|
0 0   1||a     |  |a|
*/
int a,b,MOD;
struct mat
{
    ll a[3][3]; //数组a(一般为存在幂的数组)  3为方阵的长宽
};
mat mat_mul(mat x,mat y)
{
    mat res;
    memset(res.a,0,sizeof(res.a));    //初始化
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        for(int k=0;k<3;k++)
        res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD;  //矩阵乘法
    return res;
}
void mat_pow(int n)
{
    mat c,res;
    c.a[0][0]=1,c.a[0][1]=10,c.a[0][2]=1;
    c.a[1][0]=0,c.a[1][1]=10,c.a[1][2]=1;
    c.a[2][0]=0,c.a[2][1]=0,c.a[2][2]=1;     //初始化赋值需要幂乘的数组
    
    memset(res.a,0,sizeof(res.a)); 
    for(int i=0;i<3;i++) res.a[i][i]=1;      //初始化 a的n次方的数组且对角线均为1
    
    while(n)
    {
        if(n&1) res=mat_mul(res,c);
        c=mat_mul(c,c);
        n=n>>1;
    }                                       //矩阵快速幂的运算过程
     
    int f1=a%MOD,x=a;                       //数组b的构成
    printf("%lld\n",(res.a[0][0]*f1+res.a[0][1]*x+res.a[0][2]*a)%MOD);
}
int main()
{
    int n;
    while(scanf("%d%d%d",&a,&n,&MOD)==3)
    {
        mat_pow(n-1);
    }
    return 0;
}


你可能感兴趣的:(ACM_递推,ACM_数字处理与数论,ACM_算法模板)