【HDU1757】A Simple Math Problem

题目链接

A Simple Math Problem

题目描述

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.

输入格式

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.

输出格式

For each case, output \(f\)(\(k\))\(\% m\) in one line.

样例输入

10 9999
1 1 1 1 1 1 1 1 1 1
20 500
1 0 1 0 1 0 1 0 1 0

样例输出

45
104

题解

题意:一个函数\(f\)(\(x\))满足:
\(x < 10\)时,\(f\)(\(x\))\(=x\)
\(x \ge 10\)时,\(f\)(\(x\))\(=\sum_{i=1}^{10}a_{i-1}*f\)(\(x-i\))
输入\(x\)满足\(x<2*10^9\)
\(f\)(\(x\))
看到数据范围是\(int\)范围的,那么\(O\)(\(n\))求解肯定是不行的。
看到这个函数的转移方程,是不是很像斐波那契数列呢?
众所周知,斐波那契数列有一个矩阵快速幂的加速方法,同理我们也可以用这个方法加速这个函数。
这个函数中,\(f\)(\(n\))只和他的前10项有关,那么我们构造的矩阵只需要包含\(10\)个元素就行了。
矩阵的构造如下:

那么接下来直接用矩阵快速幂加速就好了。
\(F\)(\(k\))\(=A^{k-9}*B\)
上代码:

#include<bits/stdc++.h>
using namespace std;
int k,m;
int a[19];
struct aa{
    long long a[19][19];
};
aa cc(aa x,aa y){
    aa ans;
    for(int j=1;j<=10;j++)
        for(int i=1;i<=10;i++){
            ans.a[j][i]=0;
            for(int o=1;o<=10;o++)
                ans.a[j][i]=(ans.a[j][i]+x.a[j][o]*y.a[o][i])%m;
        }
    return ans;
}
aa ksm(aa x,int p){
    aa ans;
    for(int j=1;j<=10;j++)
        for(int i=1;i<=10;i++)
            ans.a[j][i]=(j==i);
    while(p){
        if(p&1) ans=cc(ans,x);
        x=cc(x,x);
        p>>=1;
    }
    return ans;
}
int main(){
    while(scanf("%d%d",&k,&m)!=EOF){
        for(int j=1;j<=10;j++)
            scanf("%d",&a[j]);
        aa x;
        for(int j=1;j<=10;j++)
            x.a[1][j]=a[j];
        for(int j=2;j<=10;j++)
            for(int i=1;i<=10;i++)
                x.a[j][i]=(j==i+1);
        aa ans=ksm(x,k-9);
        int anss=0;
        for(int j=1;j<=10;j++)
            anss=(anss+ans.a[1][j]*(10-j))%m;
        printf("%d\n",anss);
    }
    return 0;
}
posted @ 2020-08-11 18:16  oblivionl  阅读(90)  评论(0编辑  收藏  举报