sicily 1327. Pinary

#include<iostream>        //递推关系
#include<cstring>
using namespace std;
int ans[1000],sum[1000],out[1000];
int main()
{
ans[
1]=ans[2]=1;
sum[
1]=1;sum[2]=2;
int r=2;
while(sum[r]<90000000)
{
++r;
ans[r]
=ans[r-1]+ans[r-2];
sum[r]
=ans[r]+sum[r-1];
}
int cases,n,i,res[1000],t;
cin
>>cases;
while(cases--)
{
cin
>>n;
t
=0;
while(n>0) //递归查找
{
for(i=1;sum[i]<n;++i);
res[t
++]=i;
n
=n-sum[i-1]-1;
}
memset(
out,0,sizeof(out));
for(i=0;i<t;++i)
{
out[res[0]-res[i]+1]=1; //res[0]是序列的长度
}
for(i=1;i<=res[0];++i)
cout
<<out[i];
cout
<<endl;
}
return 0;
}

/*
题意: “Pinary number”是一种只由0和1组成的数字,没有前导0,而且不能出现两个1相邻的情况。
给出一个序数k,求k对应的“Pinary number”。
例如,1对应1,2对应10,3对应100,4对应101,5对应1000
思路: 用ans[i]表示长度为i的“Pinary number”共有多少个,其中ans[1]=ans[2]=1,即 1, 10,
有 ans[i] = ans[i-1] + ans[i-2] (详细证明见后面)
然后用sum[i]表示长度小于等于i的“Pinary number”共有多少个,然后递归求k对应的“Pinary number”哪些位是1


详细说明:
ans[1]=1 , ans[2]=1 ,ans[3]=2 , ans[4]=3 , ans[5]=5 , ans[6]=8 , ans[7]=13 ,ans[8]=21 ,ans[9]=34
sum[1]=1 , sum[2]=2 ,sum[3]=4 , sum[4]=7 , sum[5]=12 , sum[6]=20 , sum[7]=33 ,sum[8]=54 ,sum[9]=88

比如 n=70的情况, 查找到 sum[8]=54<n ,sum[9]=88>=n ,说明“Pinary number”的长度为 9,第 1 个数字是 1, 继续确定余下的 8 位数字
n-=sum[8], n=16 这里要注意 n 另外还要减 1 ,n=15, 因为余下的8位,每一位都可以取 0 ,而如果只有 8位 ,第一位只能取 1
对于 n=15, 查找到 sum[5]=12<n, sum[6]=20>=n ,说明 长度现在收缩为 6 位, 第 4 个数字是 1,
联系前面得到的 9 位 ,可确定 9位 的前 四 位数字: 1001 . 此时 n-=sum[5], n=3 同样地 n 减 1, 得到 n=2
继续查找, sum[1]=1<n ,sum[2]=2>=n ,说明 长度现在收缩为 2 位, 可确定 前 八 位数字是: 100 100 01
n-=sum[1], n=1 同样地 n 减 1, 得到 n=0 ,于是退出循环,最后空缺的位置都由 0 填充,即 100 100 010 , 序列唯一确定


证明: ans[i] = ans[i-1] + ans[i-2] ,ans[i]表示长度为i的“Pinary number”共有多少个
现有一长度为 5 的序列: 10**** , 那长度为 4 的序列为: 10***,
可以看出,长度 5 的序列的第一个星号 如果取 0 ,那么ans[5]=ans[4],因为两者都只剩下 3 个星号
如果长度 5 的序列第一个星号取 1 , 则前4 个数字可确定下来: 1010** ,可以看出ans[5]=ans[3], ans[3]为 10**
故 ans[5]=ans[4]+ans[3] ,得证
*/

  

posted on 2011-07-14 15:53  sysu_mjc  阅读(226)  评论(0编辑  收藏  举报

导航