UESTC 2015dp专题 E 菲波拉契数制 dp
菲波拉契数制
Time Limit: 20 Sec Memory Limit: 256 MB
题目连接
http://acm.uestc.edu.cn/#/contest/show/65
Description
我们定义如下数列为菲波拉契数列:
F(1)=1
F(2)=2
F(i)=F(i−1)+F(i−2)(i>=3)
给定任意一个数,我们可以把它表示成若干互不相同的菲波拉契数之和。比如13有三种表示法
13=13
13=5+8
13=2+3+8
现在给你一个数n,请输出把它表示成若干互不相同的菲波拉契数之和有多少种表示法。
Input
第一样一个数T,表示数据组数,之后T行,每行一个数n。
T≤105
1≤n≤105
Output
输出T行,每行一个数,即n有多少种表示法。
Sample Input
6 1 2 3 4 5 13
Sample Output
1 1 2 1 2 3
HINT
题意
题解:
其实这道题是dp,转化成2进制做
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 200001 #define mod 10007 #define eps 1e-9 int Num; char CH[20]; //const int inf=0x7fffffff; //нчоч╢С const int inf=0x3f3f3f3f; /* inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } */ inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } //************************************************************************************** ll fib[maxn]; int topf; vector<int> vec; void init() { int i; fib[0]=fib[1]=1; for (i=2;fib[i-1]<1000000000000000000LL;i++) { fib[i]=fib[i-1]+fib[i-2]; } topf=i-1; } ll f[maxn][2]; int a[maxn]; ll n,m; int main() { int i,j,k; int x,y,z; int nn; scanf("%d",&nn); init(); while (nn--) { n=read(); vec.clear(); for (i=topf;i>0;i--) { if (fib[i]<=n) { n-=fib[i]; vec.push_back(i); } } sort(vec.begin(),vec.end()); for (i=0;i<vec.size();i++) { a[i]=(-((i)?vec[i-1]:1)+vec[i]); } f[0][1]=1; f[0][0]=a[0]/2; for (i=1;i<vec.size();i++) { f[i][0]=((a[i]-1)/2)*f[i-1][1]+((a[i])/2)*f[i-1][0]; f[i][1]=f[i-1][0]+f[i-1][1]; } printf("%lld\n",f[vec.size()-1][0]+f[vec.size()-1][1]); } return 0; }