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