这道题寒假的时候看过,还不小心看了题解,不过题解说神马早就忘了,刚开始解题的时候完全想错了,后来才想起来是用矩阵构造
这道题的确适合构造矩阵,因为所求的函数值满足线性关系,令F(N)为最终求解值
首先我们要明确如果用矩阵的作法,那么矩阵乘法中,最终矩阵,必须包含F(N),还可以包含其他函数g(n),h(n)等等。作为乘数项的矩阵不得与N有关,只能与x有关
F(n+1) = F(n) + x^(n+1)*(n+1)^x
=F(n) + (C(x,0)*n^x + C(x,1)*n^(x-1)+ ... +C(x,x-1)*n+1)*x^(n+1)
=F(n) + (C(x,0)*n^x*(x^n) + C(x,1)*n^(x-1)*(x^n)+ ... +C(x,x-1)*n*(x^n)+1*(x^n))*x
=F(n) + (x*C(x,0)*n^x*(x^n) + x*C(x,1)* n^(x-1)*x^n+...)
很明显,我把x^(n+1)*(n+1)^x 写成了sum{g(i,n)*const(i)},const(i)与n无关,可以乘数项矩阵的一部分),而g(i,n)可以作为最终矩阵的一部分
更重要的是,g(i,n)要和f(n)放在一起构成最终矩阵,也就是g(i,n)如何表达?
g(i+1,n) =(i+1)^x*(x^n) = (C(i,0)*i^x + C(i,1)*i^(x-1) + ..+C(i,i)*i^0) *(x^(n+1))
= (C(i,0)*x*t0 + C(i,1)*x*t1 + ...+C(i,i)*x*ti)
tj = i^j*(x^n) = g(j,n-1) 0<=j<=i
最终矩阵为(g(0,n),g(1,n),....g(x,n),F(n)) ,乘数矩阵这里略掉,写出来太麻烦,附代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#define N 60
#define cl(a) memset(a,0,sizeof(a))
#define ss(a) scanf("%d",&a)
#define ll __int64
#define pb push_back
using namespace std;
ll a[N][N][N],c[N][N],r[N];
vector<ll>gener;
int mod,k;
void generate_cmb()
{
int i,j;
cl(c);
for (i=0;i<=k;i++)
for (j=0;j<=i;j++)
{
if (j==0) c[i][j]=1;
else if (j>i-j) c[i][j]=c[i][i-j];
else c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
void init()
{
int i,j;
generate_cmb();
cl(a);cl(r);
for (i=0;i<=k;i++)
for (j=0;j<=k;j++)
a[0][i][j]=(k*c[i][j])%mod;
for (j=0;j<=k;j++) a[0][k+1][j]=(k*c[k][j])%mod;
a[0][k+1][k+1]=1;
for (i=0;i<=k+1;i++) r[i]=k;
}
void rmul(int x)
{
int u,v,w;
for (u=0;u<=k+1;u++)
for (v=0;v<=k+1;v++)
{
for (w=0;w<=k+1;w++)
a[x+1][u][v]=(a[x+1][u][v]+(a[x][u][w]*a[x][w][v])%mod)%mod;
}
}
void mul(int x)
{
int u,v;
ll t;
gener.clear();
for (u=0;u<=k+1;u++)
{
t=0;
for (v=0;v<=k+1;v++) t=(t+(a[x][u][v]*r[v])%mod)%mod;
gener.pb(t);
}
for (int i=0;i<=k+1;i++) r[i]=gener[i];
}
void quick(int n)
{
int i=0;
while (n>0)
{
if (n&1) mul(i);
rmul(i);
n>>=1;
i++;
}
}
int main()
{
int n;
while (ss(n)!=EOF)
{
ss(k);ss(mod);
if (n<0&&k<0&&mod<0) break;
if (n==1)
{
cout<<k%mod<<endl;
continue;
}
init();
quick(n-1);
cout<<r[k+1]<<endl;
}
return 0;
}