UVA-10479 很拽的序列

题目大意:
给出n(n<263),求“很拽的序列”H 的第n个数。
“很拽的序列”定义:
1. H(1)=0。
2. 如果把H中的每个整数x变成x个0后跟x+1,在前面附加上0仍然是H。

H序列的前16项:0,1,0,2,1,1,0,3,0,2,1,1,0,0,0,4
现在我们把定义分割再合并,出来的序列完全一样:
1.h(0)=0。
2.把h(i)中的每个整数x变成x个0后跟x+1,就等于h(i+1)。
3.把所有h(i)连在一起就是H。
我们又可以发现一个规律: h ( i ) = h ( i − 2 ) ∗ 1 + h ( i − 3 ) + 2 + . . . + h ( 0 ) ∗ i − 1 + ( i ) h(i)=h(i-2)*1+h(i-3)+2+...+h(0)*i-1+(i) h(i)=h(i2)1+h(i3)+2+...+h(0)i1+(i)
(此处乘法表示复制,加法表示连接)
接下来任务变得出奇的简单:只要求出n在h(i)里的i,就可以求出H(n)等于几了。算法是递归,还是回溯法。

代码如下:
#include <iostream>
#include <cstring>
#include <cmath>
#define llong unsigned long long
using namespace std;
llong n,f[66];
llong solve(llong n,int duan,llong len){
  if(n>=len-duan+1)return 0;
  len-=duan-1;
  for(int i=1,j=duan-2;j>0;i++,j--){
    if(n>=len-j*f[i-1]){
      n=((n-(len-j*f[i-1]))%f[i-1])+1;
      return n==f[i-1]?i:solve(n,i,f[i-1]);
    }
    len=len-j*f[i-1];
  }
}
int main(){f[0]=1;
  for(int i=1;i<64;i++)
    f[i]=f[i-1]*2;
  while(cin>>n&&n){
    int duan;
    for(int i=0;i<64;i++)
      if(n<f[i]){duan=i-1;break;}
    if(f[duan]==n)cout<<duan<<endl;
    else cout<<solve(n,duan+1,f[duan+1])<<endl;
  }
  return 0;
}

注:此题为什么题目叫“Hendrie序列”,我叫它“很拽的序列”么:因为“Hendrie”和“很拽”谐音,而且这个序列的规律太难发现了,光靠我给出的16个元素无法确定规律,因此它的确很拽!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值