1. 程式人生 > >Additions (遞推公式+矩陣快速冪)

Additions (遞推公式+矩陣快速冪)

1713: Additions

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 338  解決: 38
[提交][狀態][討論版]

題目描述

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

很久之前就寫過的一道題,暑假集訓老師拿出來講了,發現這題有多種解法,我只想到用求通項公式的方法……

方法一:通項公式法Sn=(a*(10^(n+1)-10-9*n*a)/81    取餘的時候需要一點小技巧,公式如下:
若a % b == 0
則a / b % X = a % (bX) / b

#include<bits/stdc++.h>
using namespace std;
int pow(int m,int n,int k)
{
    int t;
    if(n==0)
        return 1;
    t=pow(m,n>>1,k);
    t=(long long)t*t%k;
    if(n&1)
        t=(long long)t*m%k;
    return t;
}
int main()
{
    int a,n,m,s,k,j,t,h,y,x,i;
    const int k1=10;
    while(scanf("%d%d%d",&a,&n,&m)==3)
    {
        m=81*m;
        i=n+1;
        s=pow(k1,i,m);
        j=a%m;
        k=s*j%m;
        t=10*a%m;
        h=(9*a%m*(n%m))%m;
        y=(t+h)%m;
        x=(k-y+m)%m;
        printf("%d\n",x/81);
    }
    return 0;
}

方法二:矩陣快速冪Sn=11*Sn-1-10*Sn-2+a,注意運算溢位的問題

#include<bits/stdc++.h>
using namespace std;
int mod;
typedef struct mat
{
    int m[3][3];
}mat;
mat mul(mat a,mat b)
{
    mat t;
    memset(t.m,0,sizeof(t.m));
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        for(int k=0;k<3;k++)
        t.m[i][j]=((long long)t.m[i][j]+(long long)a.m[i][k]*b.m[k][j]+mod)%mod;
    return t;
}
mat pow_(mat a,int n)
{
    mat b;
    memset(b.m,0,sizeof(b.m));
    for(int i=0;i<3;i++) b.m[i][i]=1;
    while(n>0)
    {
        if(n&1) b=mul(b,a);
        a=mul(a,a);
        n>>=1;
    }
    return b;
}
int main()
{
    int a,n;
    while(scanf("%d%d%d",&a,&n,&mod)==3){
        mat ans;
        ans.m[0][0]=11,ans.m[0][1]=-10,ans.m[0][2]=a;
        ans.m[1][0]=1,ans.m[1][1]=0,ans.m[1][2]=0;
        ans.m[2][0]=0,ans.m[2][1]=0,ans.m[2][2]=1;
        ans=pow_(ans,n-1);
        printf("%d\n",(ans.m[0][0]*a+ans.m[0][2]+mod)%mod);
    }
}