把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P4451 [国家集训队]整数的lqp拆分

题面传送门
对于这道题,用递推的思想。
\(f_i\)表示\(i\)这个数的\(lqp\)拆分的值,那么考虑一下,除了自身的拆分,其他拆分一定是\(x\times(i-x)\),其中\(x\)是一个多数组成的集合,而\((i-x)\)是一个单个的数,然后问题就变成了怎么求\(x\)这个集合的\(lqp\)拆分的答案。因为这是递推,状态记录过,所以可直接的出结果。
代码实现:

#include<cstdio>
using namespace std;
long long f[1000039]={0,1,1},n,ans,q[1000039]={0,1,2};
int main(){
	register int i,j;
	scanf("%lld",&n);
	for(i=3;i<=n;i++) f[i]=f[i-1]+f[i-2];
	for(i=3;i<=n;i++){
		for(j=1;j<i;j++) q[i]=(q[j]*f[i-j]+q[i])%1000000007;
		q[i]=(q[i]+f[i])%1000000007;
	}
	printf("%d",q[n]);
}

但这只能过 \(5000\) 的数据,怎么办呢?
我们注意到\(q_i=\sum\limits_{j=1}^{i}{q_j'\times f_{i-j+1}}\) ,而\(q_{i-1}=\sum\limits_{j=1}^{i-1}{q_j\times f_{i-j}}\)因为 \(q_i\)的求和 中一定带有\(q_{i-1}\times f_1\) ,所以先加上去,然后观察\(q_{i-2}=\sum\limits_{j=1}^{i-2}{q_j\times f_{i-j-1}}\)\(f_{i-j-1}+f_{i-j}=f_{i-j+1}\),所以直接可得 \(q_i=q_{i-1}\times 2+q_{i-2}\)
代码实现:

#include<cstdio>
using namespace std;
long long f[1000039]={0,1,1},n,ans,q[1000039]={0,1,2};
int main(){
    register int i,j;
    scanf("%lld",&n);
    for(i=3;i<=n;i++)q[i]=(q[i-1]*2+q[i-2])%1000000007;
    printf("%lld",q[n]);
}
posted @ 2020-03-28 16:08  275307894a  阅读(55)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end