[HDU] A Very Simple Problem

我是链接

这道题做着的思路还是很不容易的,不看题解不会真的去写二项式展开。
首先求出0~50以内的C(n , m),然后我们又根据二项式定理,知道
$$ (x + 1) ^2 = \sum_{i =0}^n C(n , i) * x^i $$
(个人习惯写法的二项式定理qwq)
所以要推出 $T_n = x^{k + 1} * {k + 1} ^ x $ 需要知道前 n-1 项的 $ T_i $ 所以我们会想到用矩阵快速幂来递推所有 \(T_n\)
转换矩阵有很多种。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>

using namespace std;
typedef long long ll;
const ll N = 55;

ll Mod,C[N][N];

struct matrix{
	ll M[N][N];
	int l,r;
	
	void operator * (matrix x){
		int i,j,k;
		matrix t;
		for(i=1;i<=l;i++)
			for(j=1;j<=r;j++)
				t.M[i][j]=0;
		for(i=1;i<=r;i++)
			for(j=1;j<=x.l;j++)
				for(k=1;k<=l;k++)
					t.M[j][i] = (t.M[j][i] + M[k][i] * x.M[j][k]) % Mod;
		for(i=1;i<=l;i++)
			for(j=1;j<=r;j++)
				M[i][j]=t.M[i][j];
	}
}res,c;

void init(){
	int i,j;
	C[0][0]=1;
	for(i=1;i<=50;i++) C[i][0]=C[i][i]=1;
	for(i=1;i<=50;i++)
		for(j=1;j<i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1];
}

int main(){
	int i,j,n;
	ll x;
	init();
	while(scanf("%d%lld%lld",&n,&x,&Mod)){
		if(n==-1&&x==-1&&Mod==-1) break;
		for(i=1;i<=x+12;i++)
			for(j=1;j<=x+2;j++) if(j<=i) c.M[i][j]=(x * C[i-1][j-1]) % Mod; else c.M[i][j]=0;
		
		for(i=1;i<=x;i++) c.M[x+2][i]=0;
		c.M[x+2][x+1]=1; c.M[x+2][x+2]=1;
		c.l=x+2; c.r=x+2;
		for(i=1;i<=x+1;i++) res.M[i][1]=x;
		res.M[x+2][1]=0;
		res.l=x+2; res.r=1;
		for(; n ; n >>= 1){
			if( n & 1){
				res * c;
			}
			c * c;
		}
		printf("%lld\n",res.M[x+2][1]);
	}
	return 0;
}

posted @ 2017-12-09 14:57  FranceDisco  阅读(111)  评论(0编辑  收藏  举报