题目大意:给你一个k以及n,k代表最多走的步数,n代表一共要走的步数。
问一共有多少种方法,结果mod7777777
题目意思是很明了,具体的公式也能推出来
状态转移方程为:f[n]=f[n-1]+f[n-2]+....f[n-k]。
f[0]=1
当k=1, f[1]=1;
f[2]=f[1]=1;
f[3]=f[2]=1;
f[4]=f[3]=1;
当k=2, f[1]=1;
f[2]=f[1]+f[0]=2;
f[3]=f[2]+f[1]=3;
f[4]=f[3]+f[2]=5;
当k=3, f[1]=1;
f[2]=f[1]+f[0]=2;
f[3]=f[2]+f[1]+f[0]=4;
f[4]=f[3]+f[2]+f[1]=7;
k的数据量只有10,所以我们构造出一个10*10的矩阵,本题主要考察的是矩阵快速幂以及构造这个矩阵。
若k等于4
【 [ 0 1 0 0] [f(k-4)] [f(k-3)]
[ 0 0 1 0] * [f(k-3)] = [f(k-2)]
[ 0 0 0 1] [f(k-2)] [f(k-1)]
[ 1 1 1 1] 】 [f(k-1)] [f( k )]
根据上面的例子我们可以很容易构造出这个矩阵出来。#include<iostream>
#include<stdio.h>
#include<cstring>
#define LL long long
using namespace std;
const LL MAX = 15;
struct Matrix
{
LL v[MAX][MAX];
};
LL n, M=7777777;
Matrix mtAdd(Matrix A, Matrix B) // 求矩阵 A + B
{
LL i, j;
Matrix C;
for(i = 0; i < n; i ++)
for(j = 0; j < n; j ++)
C.v[i][j]=(A.v[i][j]+B.v[i][j])% M;
return C;
}
Matrix mtMul(Matrix A, Matrix B) // 求矩阵 A * B
{
LL i, j, k;
Matrix C;
for(i = 0; i < n; i ++)
for(j = 0; j < n; j ++)
{
C.v[i][j] = 0;
for(k = 0; k < n; k ++)
C.v[i][j] = ((A.v[i][k] * B.v[k][j])%M + C.v[i][j]) % M;
}
return C;
}
Matrix mtPow(Matrix A, LL k) // ?ó???ó A ^ k
{
if(k == 0)
{
memset(A.v, 0, sizeof(A.v));
for(LL i = 0; i < n; i ++)
A.v[i][i] = 1;
return A;
}
if(k == 1) return A;
Matrix C = mtPow(A, k / 2);
if(k % 2 == 0)
return mtMul(C, C);
else
return mtMul(mtMul(C, C), A);
}
void out(Matrix A)
{
for(LL i=0;i<n;i++)
{
for(LL j=0;j<n;j++)
cout<<A.v[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
Matrix mtCal(Matrix A, LL k) // 求S (k) = A + A2 + A3 + … + Ak
{
if(k == 1) return A;
Matrix B = mtPow(A, (k+1) / 2);
Matrix C = mtCal(A, k / 2);
if(k % 2 == 0)
return mtMul(mtAdd(mtPow(A, 0), B), C); // 如S(6) = (1 + A^3) * S(3)。
else
return mtAdd(A, mtMul(mtAdd(A, B), C)); // 如S(7) = A + (A + A^4) * S(3)
}
int main ()
{
int k;
while(~scanf("%d%d",&n,&k))
{
Matrix A;
memset(A.v,0,sizeof(A));
for(LL i=0;i<n-1;i++) A.v[i+1][i]=1;
for(LL i=0;i<n;i++) A.v[i][n-1]=1;
//out(A);
A=mtPow(A,k-1);
//out(A);
Matrix ans;
memset(ans.v,0,sizeof(ans.v));
ans.v[0][0]=1;
for(LL i=1;i<=n;i++)
{
ans.v[0][i]=1;
for(LL j=0;j<i;j++)
ans.v[0][i]+=ans.v[0][j];
}
//out(ans);
A=mtMul(ans,A);
//out(A);
cout<<A.v[0][0]<<endl;
}
}