• BZOJ.2660.[BJOI2012]最多的方案(DP)


    题目链接

    首先我们知道:
    1
    也很好理解。如果相邻两项出现在斐波那契表示法中,那它们显然可以合并。
    所以我们能得到(n)的斐波那契表示,记(pos[i])(n)的斐波那契表示法中,第(i)项在原斐波那契的下标,那么:(n=sum_{i=1}^{cnt}F[pos[i]])
    如果方案中不直接存在(F[pos[i]])(把(F[pos[i]])分解),那它只能由(<pos[i])的项构成。于是我们考虑递推。
    (f[i][1/0])表示当前考虑到(pos[i]),是/否分解(F[pos[i]]),且满足(F[pos[1]]sim F[pos[i]])都被组成,的方案数。

    如果不分解(F[pos[i]]),那么有$$f[i][0]=f[i-1][0]+f[i-1][1]$$,且(F[pos[i+1]])只能由([pos[i]+1,pos[i+1]])之间的项得到。

    如果分解(F[pos[i]]),则(F[pos[i+1]])可以由([pos[i],pos[i+1]])之间的项得到,而且若分解(F_i=F_{i-1}+F_{i-2}),下一次只能分解(F_{i-2}=F_{i-3}+F_{i-4}),再下一次只能分解(F_{i-4}=ldotsldots)。于是我们可以得到在区间([l,r-1])中分解(F_r)的方案数为(frac{r-l}{2})
    于是可以得到:$$f[i][1]=f[i-1][0] imesfrac{pos_i-pos_{i-1}-1}{2}+f[i-1][1] imesfrac{pos_i-pos_{i-1}}{2}$$

    初始值就是(f[1][0]=1,f[1][1]=frac{pos_i-1}{2})

    另外直接map记搜也能跑得飞快(甚至比递推快smg。。)

    #include <cstdio>
    #include <algorithm>
    typedef long long LL;
    const int N=100;
    
    int p[N],f[N][2];
    LL n,F[N];
    
    int main()
    {
    	scanf("%lld",&n);
    	F[1]=1, F[2]=2; int t,cnt=0;
    	for(t=3; (F[t]=F[t-1]+F[t-2])<=n; ++t);
    	for(int i=t; i; --i)
    		if(n>=F[i]) n-=F[i], p[++cnt]=i;
    	std::reverse(p+1,p+1+cnt);
    
    	f[1][0]=1, f[1][1]=p[1]-1>>1;
    	for(int i=2; i<=cnt; ++i)
    		f[i][0]=f[i-1][0]+f[i-1][1],
    		f[i][1]=f[i-1][0]*(p[i]-p[i-1]-1>>1)+f[i-1][1]*(p[i]-p[i-1]>>1);
    	printf("%d
    ",f[cnt][0]+f[cnt][1]);
    
    	return 0;
    }
    
  • 相关阅读:
    优秀程序员的45个习惯
    linq 解决winForm中控件CheckedListBox操作的问题。
    培养人脉的100个技巧
    如果可以,我想谁也不喜欢跳槽
    真我的风采
    c# 正则表代式的分组和匹配模式
    Hishop 网店系统,去版权,注册机,商业版授权
    IIS7 下 AjaxPro 失效, AjaxPro不能用,的解决办法
    Windows Server 2008 上 sql server 2008 无法连接问题
    环保,IT也需要环保,世界需要环保.
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9667017.html
Copyright © 2020-2023  润新知