http://acm.hdu.edu.cn/showproblem.php?pid=3483
求Sn=1^x * x^1 + 2^x * x^2 +...+ n^x * x^n;
要從n^x轉到(n+1)^x需要用到二項式展開公式
(n+1)^x=
C(x,0) *n^0
C(x,1) *n^1
C(x,2) *n^2
...
C(x,x) *n^x
因此可以得到:
設f(n,x)=x^n*n^x
f(n+1,x+1)=
x^(n+1)(n+1)^x=
x*C(x,0) *x^n*n^0
x*C(x,1) *x^n*n^1
x*C(x,2) *x^n*n^2
...
x*C(x,x) *x^n*n^x
=x*C(x,0) *f(n,0)
x*C(x,1) *f(n,1)
x*C(x,2) *f(n,2)
...
x*C(x,x) *f(n,x)
因此維護一個 ori矩陣 [ Sn f(n,0) f(n,1) f(n,2) ... f(n,x) ]
構造係數矩陣
相乘得到 【 S(n+1) f(n+1,0) f(n+1,1) f(n+1,2) ... f(n+1,x) 】
矩陣快速冪即可
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long mod=1000000007;
long long cc[55][55]; //內存限制爲 C(n,k)中的n*k
void pre()
{
int i,j;
for (i=0;i<=50;i++)
{
cc[i][0]=1; //c(i,0)=1;
}
for (i=1;i<=50;i++)
{
for (j=1;j<=50;j++)
cc[i][j]=(cc[i-1][j-1]+cc[i-1][j])%mod;
}
}
const int N = 52;
struct Matrix
{
long long mat[N][N];
} ;
Matrix unit_matrix ;
long long n ,x;
const int k=52;
Matrix mul(Matrix a, Matrix b) //矩陣相乘
{
Matrix res;
for(int i = 0; i < k; i++)
for(int j = 0; j < k; j++)
{
res.mat[i][j] = 0;
for(int t = 0; t < k; t++)
{
res.mat[i][j] += a.mat[i][t] * b.mat[t][j];
res.mat[i][j] %= mod;
}
}
return res;
}
Matrix pow_matrix(Matrix a, long long m) //矩陣快速冪
{
Matrix res = unit_matrix;
while(m != 0)
{
if(m & 1)
res = mul(res, a);
a = mul(a, a);
m >>= 1;
}
return res;
}
Matrix get(long long n,long long x)
{
Matrix ori;
memset( ori.mat ,0,sizeof ori.mat);
ori.mat[0][0]=x;
for (int i=1;i<x+2;i++) ori.mat[0][i]=x%mod;
Matrix c;
memset( c.mat ,0,sizeof c.mat);
c.mat[0][0]=1%mod;
for (int i=1;i<x+2;i++)
c.mat[i][0]=x*cc[x][i-1]%mod;
for( int i=1;i<x+2;i++)
for (int j=1;j<i+1;j++)
c.mat[j][i]=x*cc[i-1][j-1]%mod;
Matrix ans = pow_matrix(c, n-1);
ans = mul(ori,ans);
return ans;
}
int main()
{
int i, j, t;
//初始化單位矩陣 //類似快速冪的 ans=1; 如今是ans=單位矩陣
memset(unit_matrix.mat,0,sizeof unit_matrix.mat);
for(i = 0; i < k; i++) unit_matrix.mat[i][i] = 1;
while(scanf("%lld%lld%lld",&n,&x,&mod))
{
if (n<0&&x<0&&mod<0)return 0;
pre();
Matrix tmp=get(n,x);
long long ans=tmp.mat[0][0] ;
printf("%lld\n",(ans));
}
return 0;
}