【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
",anss);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/linjiale/p/13477454.html