这题目。。。还是和上次CF的E题差不多(其实是阉割版)。
注意到x比较小。。。所以可以考虑二项展开再利用矩阵就能求解。
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAX 128
using namespace std;
typedef __int64 i64;
i64 MOD;
i64 cb[MAX][MAX];
i64 v[MAX];
//先初始化cb数组都为-1
i64 calc(int n, int k) {
if (!k || n == k) return 1;
if (~cb[n][k]) return cb[n][k];
return cb[n][k] = (calc(n - 1, k - 1) + calc(n - 1, k)) % MOD;
}
i64 a[MAX][MAX], b[MAX][MAX], c[MAX][MAX], buff[MAX][MAX], vec[MAX];
void matCpy(i64 a[MAX][MAX], i64 b[MAX][MAX], int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
a[i][j] = b[i][j];
}
}
}
void norm(i64 a[MAX][MAX], int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
a[i][j] = (i == j);
}
}
}
void matMul(const i64 a[MAX][MAX], const i64 b[MAX][MAX], i64 c[MAX][MAX], int n) {
int i, j, k;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
for (c[i][j] = k = 0; k < n; ++k) {
c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;
}
}
}
}
void matPow(i64 a[MAX][MAX], i64 b, i64 c[MAX][MAX], int n) {
for (norm(c, n); b; b >>= 1) {
if (b & 1) {
matMul(c, a, buff, n);
matCpy(c, buff, n);
}
matMul(a, a, buff, n);
matCpy(a, buff, n);
}
}
int main(){
i64 n;
int x;
while(scanf("%I64d%d%I64d",&n,&x,&MOD)!=EOF)
{
if(n<0&&MOD<0&&x<0) break;
for(int i=0;i<60;i++) for(int j=0;j<60;j++) cb[i][j]=-1;
memset(a,0,sizeof(a));
a[0][0]=1,a[0][1]=1;
for(int i=1;i<x+2;i++){
for(int j=i;j<x+2;j++){
a[i][j]=(x%MOD)*calc(x+1-i,j-i)%MOD;
}
}
matPow(a,n,b,x+2);
v[0]=0;
i64 ans=0;
for(int i=1;i<x+2;i++) v[i]=x%MOD;
for(int i=0;i<x+2;i++) ans=(ans+b[0][i]*v[i]%MOD)%MOD;
printf("%I64d\n",(ans+MOD)%MOD);
}
return 0;
}