bzoj2660最多的方案

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2660

当然可以看出  选了第 i 个斐波那契数<=>选了第 i - 1 和第 i - 2 个斐波那契数;

还有一个关键是:题目给出的这个数能表示成几个斐波那契数的和<=>该数可以被用斐波那契数分解。

如果把选不选每一个斐波那契数用二进制表示的话,首先要尽量使最高位最大,才能算出最多的方案。

把第一次分解的那些斐波那契数的位置记录下来,用dp表示这些数选不选。

  若选这个数,则上一个选了或者没选而分解到更小的都行;

  若不选这个数,则它的方案数画一画就知道是  它与上一个分解出的数中间的0的个数 * 选上一个数 + (……0的个数+1)*不选上一个数;

我觉得自己应该好好利用斐波那契数的这个写在第一行的性质。本题怎么可能不与这有关呢?

  自己考虑到“上一个数也可以不选而……”的时候就不行了,这是没有考虑到利用自己假设已经算出来的值(即“不选这个数的方案数”);还是经验不足吧。

蜜汁:注释掉的部分有什么不对?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e6+5;
ll n,c[N],cnt,dp[90][2],pos[N],xnt;
int main()
{
    scanf("%lld",&n);
    c[1]=1;c[0]=1;
    for(int i=2;c[i-1]<=n;i++)c[i]=c[i-1]+c[i-2],cnt=i-1;
    for(int i=cnt;i&&n;i--)if(c[i]<=n)n-=c[i],pos[++xnt]=i;
//    dp[xnt][1]=1;dp[xnt][0]=(pos[xnt]-1)/2;/////
//    for(int i=xnt-1;i;i--)
//    {
//        dp[i][1]=dp[i+1][0]+dp[i+1][1];
//        dp[i][0]=dp[i+1][0]*(pos[i]-pos[i+1])/2+dp[i+1][1]*(pos[i]-pos[i+1]-1)/2;
//    }
//    printf("%lld",dp[1][0]+dp[1][1]);
    sort(pos+1,pos+xnt+1);
    dp[1][1]=1;dp[1][0]=(pos[1]-1)/2;
    for(int i=2;i<=xnt;i++)
    {
        dp[i][1]=dp[i-1][1]+dp[i-1][0];
        dp[i][0]=(pos[i]-pos[i-1])/2*dp[i-1][0]+(pos[i]-pos[i-1]-1)/2*dp[i-1][1];
    }
    printf("%lld",dp[xnt][0]+dp[xnt][1]);
    return 0;
}

 

posted on 2018-06-04 16:18  Narh  阅读(147)  评论(0编辑  收藏  举报

导航