【SNOI2017 DAY1】礼物

Problem

传送门

定位:二项式定理+矩阵乘法

\(S_i=A_1+A_2+...+A_i\)
\(A_i=S_{i-1}+i^K,S_i=S_{i-1}+A_i=2S_{i-1}+i^K\)

发现,这是一个递推式,而\(n \leq 10^{18}\),不难想到用矩阵去优化转移。

现在难点在于\((i+1)^K\)如何通过\(i\)转移而来,不难通过二项式定理
\((i+1)^K=\sum C_{n-k}^{k} i^k \times 1^{n-k}\)
所以可以构造出一下矩阵:

\[\begin{gathered} \begin{pmatrix} S_i & n^K & n^{K-1} & n^{K-2} & ... & n^0 \end{pmatrix} \quad \end{gathered} \times \begin{gathered} \begin{pmatrix} 2 & 0 & 0 & 0 & 0 & ...\\ 0 & C & 0 & 0 & 0 & ...\\ 0 & C & C & 0 & 0 & ...\\ ... & \\ \end{pmatrix} \quad \end{gathered} \]

C代指二项式定理各项系数(其实就是杨辉三角)

\(code:\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
int N;
struct Matrix{
	ll x[12][12];
	Matrix(){for(int i=0;i<N;i++) for(int j=0;j<N;j++) x[i][j]=0;}
};
inline Matrix operator * (Matrix a,Matrix b){
	Matrix c;
	for(int i=0;i<N;i++) for(int j=0;j<N;j++) c.x[i][j]=0;
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			for(int k=0;k<N;k++){
				c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j]%mod)%mod;
			}
		}
	}
	return c;
}
ll n;
int k;
Matrix A,B;
Matrix ksm(Matrix x,ll y){
	Matrix res;
	for(int i=0;i<N;i++) res.x[i][i]=1;
	while(y){
		if(y&1) res=res*x;
		x=x*x;
		y>>=1;
	}
	return res;
}
int main(){
	cin>>n>>k;
	N=k+2;
	for(int i=1;i<N;i++) A.x[0][i]=1;
	B.x[0][0]=2,B.x[1][0]=1;
	for(int i=N-1;i>=1;i--){
		B.x[N-1][i]=1;
		for(int j=N-2;j>=i;j--)
			B.x[j][i]=B.x[j+1][i+1]+B.x[j][i+1];
	}
	A=A*ksm(B,n-1);
	Matrix C=A*B;
	printf("%lld\n",(C.x[0][0]-A.x[0][0]+mod)%mod);
	return 0;
}
posted @ 2022-02-28 20:43  Thermalrays  阅读(26)  评论(0编辑  收藏  举报