zoukankan      html  css  js  c++  java
  • BZOJ_5015_[Snoi2017]礼物_矩阵乘法

    BZOJ_5015_[Snoi2017]礼物_矩阵乘法

    Description

    热情好客的请森林中的朋友们吃饭,他的朋友被编号为 1~N,每个到来的朋友都会带给他一些礼物:。其中,第
    一个朋友会带给他 1 个,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的 K 
    次方那么多个。所以,假设 K=2,前几位朋友带来的礼物个数分别是:1,5,15,37,83假设 K=3,前几位朋友带来的
    礼物个数分别是:1,9,37,111现在,好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。已知 N,K请输
    出第 N 个朋友送的礼物个数 mod1000000007。

    Input

    第一行,两个整数 N,K
    N≤10^18,K≤10

    Output

    一个整数,表示第 N 个朋友送的礼物个数 mod1000000007。 

    Sample Input

    4 2

    Sample Output

    37

    设序列的前缀和为$S_n$,$S_n=S_{n-1}+n^{k}$。
    $(S_{n-1}; n^{k}; ...n^{0})$ -> $(S_{n};(n+1)^{k};...(n+1)^{0})$
    转移矩阵发现可以用二项式定理。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    int m;
    ll n,mod=1000000007,c[15][15];
    struct Mat {
    	ll v[14][14];
    	Mat(){memset(v,0,sizeof(v));}
    	Mat operator*(const Mat &x)const {
    		Mat re;int i,j,k;
    		for(i=1;i<=m;i++) {
    			for(j=1;j<=m;j++) {
    				for(k=1;k<=m;k++) {
    					(re.v[i][j]+=v[i][k]*x.v[k][j]%mod)%=mod;
    				}
    			}
    		}
    		return re;
    	}
    };
    void print(Mat x) {
    	int i,j;
    	for(i=1;i<=m;i++) {
    		for(j=1;j<=m;j++) {
    			printf("%lld ",x.v[i][j]);
    		}
    		puts("");
    	}
    }
    Mat qp(Mat x,ll y) {
    	Mat I;
    	int i;
    	for(i=1;i<=m;i++) I.v[i][i]=1;
    	while(y) {
    		if(y&1ll) I=I*x;
    		x=x*x;
    		y>>=1ll;
    	}
    	return I;
    }
    Mat build() {
    	Mat x;
    	int i,j;
    	x.v[1][1]=2; x.v[2][1]=1;
    	for(i=2;i<=m;i++) {
    		int k=m-i+1;
    		for(j=0;j<=k;j++) {
    			x.v[j+i][i]=c[k-1][j];
    		}
    	}
    	/*for(i=1;i<=m;i++) {
    		for(j=1;j<=m;j++) {
    			printf("%lld ",x.v[i][j]);
    		}
    		puts("");
    	}*/
    	return x;
    }
    void init() {
    	int i,j;
    	for(i=0;i<=m;i++) c[i][0]=c[i][i]=1;
    	for(i=1;i<=m;i++) {
    		for(j=1;j<=m;j++) {
    			c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    		}
    	}
    }
    int main() {
    	scanf("%lld%d",&n,&m); m+=2;
    	init();
    	Mat A;
    	int i;
    	for(i=2;i<=m;i++) A.v[1][i]=1;
    	Mat x=build();
    	Mat T=A*qp(x,n-1);
    	//print(T);
    	printf("%lld
    ",((T*x).v[1][1]-T.v[1][1]+mod)%mod);
    }
    
  • 相关阅读:
    技术人员转型秘笈
    2007 Office System Beta2 Technical Refresh 下载
    使用Word 2007写blog
    SharePoint WebPart 用户控件包装器 HandsOn Labs
    将Office SharePoint Server 2007 Beta2安装到DC上
    Visual Studio Tools for Office “v3” CTP!
    QuickPart : 用户控件包装器 for SharePoint 2007
    Office SharePoint Server 2007 !
    说说ASP.NET 2.0的书
    闫辉的书:《程序员,建立你的商业意识》
  • 原文地址:https://www.cnblogs.com/suika/p/8901964.html
Copyright © 2011-2022 走看看