数据很大,以背包的思路数组开不下。

  先定序地考虑一个菲波拉契数如fib(i)的表示法,假设i比较大,由菲波拉契数的定义可知道fib(i)=fib(i-1)+fib(i-2);要找到其它表示就继续拆分fib(i-1)或fib(i-2),假如拆分fib(i-1)得到fib(i)=2*fib(i-2)+fib(i-3),这不能保证保证互不相同的性质(补充,也许有人会考虑将这个式作为中间过程通过拆出矛盾项来保证唯一性,然而消除了一个矛盾必然产生新的矛盾,所以不行,具体地说将fib(i-2)=fib(i-3)+fib(i-4)消除了fib(i-2)的矛盾然而产生了fib(i-3)的矛盾,fib(i-3)又是由fib(i-1)得来,无法通过有限次拆分将矛盾消除),因此考虑拆fib(i-2),又得到一种表达方式fib(i)=fib(i-1)+fib(i-3)+fib(i-4);继续拆分,和前面类似,只能拆fib(i-4);不难发现每次只能拆最小的fib数,终点为fib(1)或fib(2);由上面过程可以得出:1或2+2*m=i,m是除了fib(i)本身以外其他的表示方法,上式可以得出m=(i-1)/2(/都表示向下取整,下同)。
  ok,我们成功地解决了n为菲波拉契数的情况;下面考虑n为菲波拉契数的组合的情况;假设n=fib(i)+fib(j),i>j;我们知道fib(i)和fib(j)单独的情况,现在组合起来可以借鉴刚刚拆分的思想,不同的是现在可能fib(i)和fib(j)都可以拆分;假设拆分fib(j)(可能你要问,为什么要拆小的那个?原因是在fib(i)拆分中会有和fib(j)拆分冲突的情况)得到(j-1)/2+1组;现在考虑拆fib(i),和一开始一样的思想只是终点发生了变化,为确定终点(保证独立性),我们考察fib(j)的拆分情况,我们发现在(j-1)/2种拆分中都是以fib(j-1)开头的,因此终点为fib(j)或fib(j+1),可以得到等式2*m1+j或(j+1)=i,m1=(i-j)/2,m1是除了fib(i)本身以外其他的表示方法;以fib(j)开头,即fib(j)本身,终点为fib(j+1)或fib(j+2),m2=(i-j-1)/2,m2是除了fib(i)本身以外其他的表示方法。综上,含fib(i)的表示有(j-1)/2+1种,不含fib(i)的表示有m1*(j-1)/2+m2。现在推广到n=fib(i)+fib(j)+fib(k),i>j>k的情况fib(j)和fib(k)的组合已经知道了,而且分两组以fib(j)开头的和以fib(j-1)开头的,对fib(i)拆分和上一种办法一样,由此给出dp[i][0]的定义:以fib(i-1)开头的所有组合,dp[i][1]:以fib(i)开头的所有组合。于是有状态转移方程dp[i][1]=dp[j][0]+dp[j][1],dp[i][0]=(i-j-1)/2*dp[j][1]+(i-j)/2*dp[j][0],最终结果为dp[maxi][0]+dp[maxi][1]。

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std; long long int dp[][];//dp[i][0] 表示comb[0~i]的所有组合的降序排列中以fib[i-1]开头的 [1]表示以fib[i]开头的
long long int fib[]; void get_fibs()
{
fib[]=;fib[]=;
for(int i=;i<;i++)
fib[i]=fib[i-]+fib[i-];
}
vector<int> comb;//组成n的fib的下标
long long int n;
void solve()
{
comb.clear();
for(int i=;i>&&n;i--)
if(n>=fib[i])
{
n-=fib[i];
comb.push_back(i-);
}
sort(comb.begin(),comb.end());
dp[][]=;
dp[][]=comb[]/;
for(int i=;i<comb.size();i++)
{
dp[i][]=dp[i-][]+dp[i-][];
dp[i][]=(comb[i]-comb[i-]-)/*dp[i-][]+(comb[i]-comb[i-])/*dp[i-][];
}
printf("%lld\n",dp[comb.size()-][]+dp[comb.size()-][]);
} int main()
{
get_fibs();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
solve();
}
return ;
}

[dp][uestc]L - 菲波拉契数制升级版的更多相关文章

  1. UESTC_菲波拉契数制升级版 2015 UESTC Training for Dynamic Programming<Problem L>

    L - 菲波拉契数制升级版 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Su ...

  2. UESTC 2015dp专题 E 菲波拉契数制 dp

    菲波拉契数制 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/65 Descr ...

  3. [dp]uestc oj E - 菲波拉契数制

    E - 菲波拉契数制 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  4. Contest20140906 ProblemC 菲波拉契数制 DP

    C.菲波拉契数制时间:2s   内存:65536KB我们定义如下数列为菲波拉契数列:                    F (1) = 1                    F (2) = 2 ...

  5. UESTC_菲波拉契数制 2015 UESTC Training for Dynamic Programming<Problem E>

    E - 菲波拉契数制 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  6. CDOJ 1133 菲波拉契数制 变直接统计为构造

    菲波拉契数制 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit St ...

  7. 递归函数练习:输出菲波拉契(Fibonacci)数列的前N项数据

    /*====================================================================== 著名的菲波拉契(Fibonacci)数列,其第一项为0 ...

  8. e8_4输出菲波拉契数列的前10项

    program fbnq;{输出菲波拉契数列的前10项} var a:..] of integer; i:integer; begin a[]:=; a[]:=; do a[i]:=a[i-]+a[i ...

  9. C语言-郝斌笔记-005菲波拉契序列

    菲波拉契序列 /* 菲波拉契序列 1 2 3 5 8 13 21 34 */ # include <stdio.h> int main(void) { int n; int f1, f2, ...

随机推荐

  1. 3dmax室内设计,建筑视频

    第一教程篮球场 http://video.1kejian.com/video/?30800-0-1.html 第一课 元素级别-flip反转(直接看模型里面) 第二课 alt+r = ring crt ...

  2. php如何判断文件是否存在,包括本地和远程文件

    当检查的文件是本地时用PHP自带的file_exists检查就行了,而此函数只能检查本地的函数是否存在, 所以如果要检查远程的文件是否存在只能用其它的方法了. 如果所服务器中php的配置开启了“all ...

  3. 洛谷P3264 [JLOI2015]管道连接(斯坦纳树)

    传送门 感觉对斯坦纳树还是有很多疑惑啊…… 等到时候noip没有爆零的话再回来填坑好了 //minamoto #include<iostream> #include<cstdio&g ...

  4. 管理docker容器

    如果在容器中启动sshd,存在开销和攻击面增大的问题.同时也违反了Docker所倡导的一个容器一个进程的原则. docker attach 37d61466c69e \\注意:如果在stdin中exi ...

  5. IDEA导入HttpServlet包

    转载此篇博客,言简意赅.https://blog.csdn.net/liu_yanzhao/article/details/78838670

  6. JavaScript进阶 - 第3章 一起组团(数组)

    第3章 一起组团(数组) 3-1 一起组团(什么是数组) 我们知道变量用来存储数据,一个变量只能存储一个内容.假设你想存储10个人的姓名或者存储20个人的数学成绩,就需要10个或20个变量来存储,如果 ...

  7. String常用方法简介

    1. 创建String对象的常用方法 (1) String s1 = "mpptest" (2)  String s2 = new String(); (3) String s3 ...

  8. CF620E New Year Tree 状压+线段树(+dfs序?)

    借用学长的活:60种颜色是突破口(我咋不知道QAQ) 好像这几道都是线段树+dfs序??于是你可以把60种颜色压进一个long long 里,然后向上合并的时候与一下(太妙了~) 所以记得开long ...

  9. js window对象属相和方法相关整理资料

    window对象有以下方法: open close alert confirm prompt setTimeout clearTimeout setInterval clearInterval mov ...

  10. Swagger 2.0 集成配置

    传统的API文档编写存在以下几个痛点: 对API文档进行更新的时候,需要通知前端开发人员,导致文档更新交流不及时: API接口返回信息不明确 大公司中肯定会有专门文档服务器对接口文档进行更新. 缺乏在 ...