不是很会构造矩阵,耗费了十几页的A4纸!!!
构造矩阵:
坑点:
- S(n)=k(一般首项为1)
- 构造矩阵时要取模(不只是在运算过程中取模,平时构造的矩阵不取模是因为模数一般为1e9+7,只用运算过程中才会超过模数。)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int Max_n=55;
ll k,mod;
int x,n;
ll c[Max_n][Max_n];
ll s[Max_n][Max_n];
void getC(){ //得到组合数C(i,j)
memset(c,0,sizeof(c));
for(int i=0;i<=50;i++)c[i][0]=1;
for(int i=1;i<=50;i++){
for(int j=1;j<=50;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
// for(int i=0;i<10;i++){
// for(int j=0;j<10;j++)printf("%4lld ",c[i][j]);
// cout<<endl;
// }
}
struct Mat{ // 矩阵
ll m[Max_n][Max_n];
Mat(){memset(m,0,sizeof(m));}
Mat(ll s[Max_n][Max_n]){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
m[i][j]=s[i][j];
}
}
Mat operator*(Mat &a){
Mat b;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
b.m[i][j]=(b.m[i][j]+m[i][k]*a.m[k][j])%mod;
}
return b;
}
};
Mat quickMod(Mat base,ll exp){ //矩阵乘法
Mat ans;
for(int i=0;i<n;i++)ans.m[i][i]=1;
while(exp){
if(exp&1)ans=ans*base;
exp>>=1;
base=base*base;
}
return ans;
}
int main()
{
getC();
while(cin>>k>>x>>mod){
if(k==-1&&x==-1&&mod==-1)break;
n=x+2;
memset(s,0,sizeof(s)); // 构造矩阵S
s[0][0]=1;
for(int i=1;i<n;i++)s[0][i]=c[x][i-1]%mod;
for(int i=1;i<n;i++){
for(int j=i;j<n;j++)
s[i][j]=(x*c[x+1-i][j-i])%mod;
}
// for(int i=0;i<n;i++){
// for(int j=0;j<n;j++)printf("%4lld ",s[i][j]);
// cout<<endl;
// }
Mat ans(s);
Mat t=quickMod(ans,k-1);
ll sum=t.m[0][0]*x%mod;
for(int i=1;i<n;i++)
sum=(sum+t.m[0][i]*x*x)%mod;
cout<<sum<<endl;
}
return 0;
}