zoukankan      html  css  js  c++  java
  • 题解 SP6286 【SUMMUL

    这题首先我们可以推出递推式:

    我们先把加数个数大于等于 (2) 的限制去掉,最后再减回去即可。

    [f_0=1 ]

    [f_n=sumlimits_{i=1}^{n} j cdot f_{i-j} ]

    暴力代码:

    #include<bits/stdc++.h>
    using namespace std;
    template<typename T>inline void read(T& FF){
    	FF=0;T RR=1;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int f[100010];
    int main(){int T;read(T);while(T--){
    	int n;read(n);
    	f[0]=1;
    	for(int i=1;i<=n;i++){
    		f[i]=0;
    		for(int j=1;j<=i;j++)
    			f[i]+=j*f[i-j];
    	}
    	cout<<f[n]-n<<endl;}
    	return 0;
    }
    

    然后我们看这个东西怎么矩乘。

    我们来做差。

    [egin{aligned}f_n-f_{n-1}&=sumlimits_{i=1}^{n} j cdot f_{i-j}-sumlimits_{i=1}^{n-1} j cdot f_{i-j-1}\&=f_{i-1}+2cdot f_{i-2}+cdots + icdot f_{0}-[f_{i-2}+2cdot f_{i-3}+cdots + (i-1)cdot f_{0}]\&=f_{i-1}+f_{i-2}+cdots+f_{0}end{aligned} ]

    我们把这个东西叫做 (g_{i-1})

    那么,现在矩阵乘法要做的事情就是利用 (f_{i-1})(g_{i-1}) 求出 (f_i),我们发现 (f_i=f_{i-1}+g_{i-1}),故可得矩阵:

    [egin{bmatrix}1&1\1&2\end{bmatrix}egin{bmatrix}f_{i-1}\g_{i-1}end{bmatrix}=egin{bmatrix}f_{i}\g_{i}end{bmatrix} ]

    然后我们可以得到:

    [egin{bmatrix}0\1end{bmatrix}egin{bmatrix}1&1\1&2end{bmatrix}^n ]

    用矩乘算一下即可。

    (code)

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    const int N=5,MOD=1000000007;
    struct Matrix{
    	int a[N][N],n,m;
    	Matrix(){
    		memset(a,0,sizeof(a));
    	}
    	void build(){
    		for(int i=1;i<=2;i++)a[i][i]=1;
    	}
    }a,ans;
    Matrix operator*(const Matrix x,const Matrix y){
    	Matrix ans;
    	ans.n=x.m;
    	ans.m=y.n;
    	for(int k=1;k<=x.m;k++)
    		for(int i=1;i<=x.n;i++)
    			for(int j=1;j<=y.m;j++)
    				ans.a[i][j]=(ans.a[i][j]+1ll*x.a[i][k]*y.a[k][j]%MOD)%MOD;
    	return ans;
    }
    Matrix pw(Matrix a,int k){
    	Matrix ans;ans.n=ans.m=2;ans.build();
    	for(;k;k>>=1,a=a*a)
    		if(k&1)ans=ans*a;
    	return ans;
    }
    signed main(){
    	int T;read(T);
    	while(T--){
    		int n;read(n);
    		Matrix a,b;
    		a.n=2;a.m=2;
    		a.a[1][1]=a.a[1][2]=a.a[2][1]=1;a.a[2][2]=2;
    		b.n=2;b.m=1;
    		b.a[1][1]=0;b.a[2][1]=1;
    		a=pw(a,n);
    		a=a*b;
    		cout<<(a.a[1][1]-n+MOD)%MOD<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    #Leetcode# 21. Merge Two Sorted Lists
    #Leetcode# 118. Pascal's Triangle
    #LeetCode# 136. Single Number
    #Leetcode# 26. Remove Duplicates from Sorted Array
    #LeetCode# 167. Two Sum II
    #Leetcode# 58. Length of Last Word
    #LeetCode# 35. Search Insert Position
    POJ 2492 J-A Bug's Life
    #Leetcode# 27. Remove Element
    【前端】.easyUI.c#
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/14218780.html
Copyright © 2011-2022 走看看