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;
}



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