CF(D. Fibonacci Sums)dp计数

来源:互联网 发布:排名优化软件 编辑:程序博客网 时间:2024/05/22 15:05

题目链接:http://codeforces.com/contest/126/problem/D

题意:一个数可以有多种由互不相同的斐波那契数组成的情况;


解法:dp,容易证明:每个数通过贪心可以找到一种最少数量的斐波那契数组成方案;然后找到有多少种代替的方案;dp[i][0]表示前i个里面第i个数不动的方案数,dp[i][1]表示前i个里面第i个数下放的方案数,因为下放最多下放到已经有了的数,而且下放过程中,i下放,那么i-1就会固定无法下放,最多只能继续下放i-2,直到下放到已经存在的数位置。转移方程见代码:


代码:

/******************************************************* @author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8#define zero(_) (abs(_)<=eps)const double pi=acos(-1.0);typedef long long LL;const int Max=100010;const int INF=1e9+7;LL fi[120];int tool[100];int p=0;LL dp[100][2];int main(){    fi[1]=1;    fi[2]=2;    for(int i=3; i<=90; i++)        fi[i]=fi[i-1]+fi[i-2];       // cout<<fi[90]<<endl;    int t=0;    LL a;    scanf("%d",&t);    while(t--)    {        p=0;        cin>>a;        int x=90;        while(a)        {            if(fi[x]<=a)            {                tool[p++]=x;                a-=fi[x];            }            //cout<<a<<" "<<x<<endl;            x--;        }        reverse(tool,tool+p);        dp[0][0]=1;        dp[0][1]=(tool[0]-1)/2;        for(int i=1;i<p;i++)        {           dp[i][0]=dp[i-1][0]+dp[i-1][1];           dp[i][1]=(tool[i]-tool[i-1]-1)/2*dp[i-1][0]+                    (tool[i]-tool[i-1])/2*dp[i-1][1];        }        cout<<dp[p-1][0]+dp[p-1][1]<<endl;    }    return 0;}

0 0
原创粉丝点击