• P4133 [BJOI2012]最多的方案 题解


    原题链接

    简要题意:

    \(f\) 表示斐波那契数列。给定一个 \(n\) ,求将 \(n\) 分解为 \(f\) 中若干个 不同 的数的和的方案数。

    \(n \leq 10^{18}\). 时间限制 \(0.5s\).

    这题想给大家分享一个能简单过掉的办法。

    先把 \(f\) 写出来:

    \[\begin{cases} f_n = 1 \space \space \space\space \space \space\space \space \space\space \space \space\space \space \space\space \space \space\space \space (n \leq 2) \\ f_n = f_{n-1} + f_{n-2} \space \space \space (n > 2) \\ \end{cases}\]

    写一个小程序验证一下,你就会发现,\(f_{88} = 1100087778366101931\) 已经超过了 \(10^{18}\)

    所以实际参与分解的只可能是 \(f_1 - f_{87}\).

    注意到有 \(30 \%\) 的数据,\(n \leq 256\),肯定是直接爆搜 \(f\) 取和不取。但实际上,\(n \leq 10^{18}\) 又为什么不能?

    考虑暴力。

    \((x,p)\) 作为一个状态,表示现在在决策 \(f_x\) 取或不取,和为 \(p\).

    暴力考虑 \(f_x\) 取或不取。

    加几个剪枝。我们可以取 \(s\) 作为 \(f\) 的前缀和,那么如果 \(p \geq s_x\),可以直接得出答案,防止连续不选太多导致大量冗余搜索。

    于是我们可以得到第一份代码。

    (注意:题目里有个细节,取的是 \(f\) 中不同的数,也就是不能取两个 \(1\),这点需要稍微弄一下)

    Link.

    尽管本机对于一些极限数据需要跑到 \(0.55s\) 左右,但在洛谷的评测机之下,毫无疑问,这通过了。

    我们希望有一种更优的方法。

    我们会发现,对于 \((x,p)\) 状态的个数其实是极为有限的。如果你用 map 计数的话,会发现即使对于 \(n = 10^{18}\) 看起来极为复杂的这一种情况,其实状态个数也没有超过 \(250\).

    于是我们自然而然地想到了:记忆化搜索。

    在暴力的基础上加一个 map,对于冗余的状态直接跳过。

    时间复杂度:\(\mathcal{O}(\texttt{wys})\).

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 88;
    typedef long long ll;
    
    ll f[N],s[N],n;
    
    map<pair<ll,ll>,ll> q;
    
    inline ll dfs(register ll x , register ll p) {
        if(q[make_pair(x,p)]) return q[make_pair(x,p)];
    	if(!x) return 0;
    	if(!p) return 1;
    	if(p > s[x]) return 0;
    	if(p == s[x]) return 1;
        ll ans = 0;
    	if(p >= f[x]) ans += dfs(x - 1 , p - f[x]);
    	ans += dfs(x - 1 , p);
        return q[make_pair(x,p)] = ans;
    }
    
    int main() {
    	f[0] = f[1] = 1;
    	s[0] = 0 , s[1] = 1;
    	for(int i = 2; i < N; i++) {
    		f[i] = f[i - 1] + f[i - 2];
    		s[i] = s[i - 1] + f[i];
    	}
    	scanf("%lld",&n);
    	printf("%lld\n",dfs(86,n));
    	return 0;
    }
    
  • 相关阅读:
    文献收录船舶建造的现代工程分解结构
    FLEX MDI窗口开发实例(2)
    收录国外造船信息Pursuit of a product work breakdown structure (PWBS)
    FLEX MDI窗口开发实例
    买了本<<flash actionscript 3.0殿堂之路>>
    今天我捐款了
    记Lambda的一个使用方法
    JXMS 低代码开发平台
    我的博客也Sliverlight
    代码编辑插件使用
  • 原文地址:https://www.cnblogs.com/bifanwen/p/15846546.html
Copyright © 2020-2023  润新知