51nod1064 序列中最大的数 V3

该博客介绍了一个数学序列a,其定义为a[0]=0, a[1]=1, a[i]=a[2i] 或 a[i]=a[i]+a[i+1]。根据输入的数N,计算并找出a[0]-a[N]之间的最大值。例如,当N=5时,最大值为3;当N=10时,最大值为4。博客提供了C++、Java和Python的代码实现。" 106567646,8506500,Centroids 解题思路与算法,"['算法', '动态规划', '数据结构', '竞赛编程', '树形结构']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1064 序列中最大的数 V3

有这样一个序列a:

a[0] = 0

a[1] = 1

a[2i] = a[i]

a[2i+1] = a[i] + a[i+1]

输入一个数N,求a[0] - a[n]中最大的数。

a[0] = 0, a[1] = 1, a[2] = 1, a[3] = 2, a[4] = 1, a[5] = 3, a[6] = 2, a[7] = 3, a[8] = 1, a[9] = 4, a[10] = 3。

例如:n = 5,最大值是3,n = 10,最大值是4。

输入

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:T个数,表示需要计算的n。(1 <= n <= 10^100)

输出

共T行,每行1个最大值。

输入样例

2
5
10

输出样例

3
4

这里就不给解析,只放代码:

c++代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define  LL  long long
#define  Z2  60
#define  Z2H 30
#define  M2  ((1LL << Z2) - 1)
#define  M2H ((1LL << Z2H) - 1)
#define  Z10  18
#define  M10  1000000000000000000LL
#define  MAXN  (1LL << 60)
class  bigint_2t;
class  bigint_10t {
public:
	bigint_10t() { memset( data, 0, sizeof(data) ); }
	void  assign( LL x ) { data[0] = ( x % M10 ); data[1] = (x / M10); }
	void  assign( bigint_10t& x ) {
		memcpy( data, x.data, sizeof(data) );
	}
	void  add( bigint_10t & x ) {
		LL  carry = 0;
		for( int i = 0; i < 6; ++i ) {
			data[i] = data[i] + x.data[i] + carry;
			carry = (data[i] / M10);
			data[i] %= M10;
		}
	}
	bool  operator <= ( bigint_10t& x ) {
		for( int i = 5; i >= 0; --i ) {
			if( data[i] < x.data[i] ) return  true;
			else if( data[i] > x.data[i] ) return  false;
		}
		return  true;
	}
	void  read() {
		char  buf[128];
		scanf( "%s", buf );
		int  len = strlen( buf );
		int  i = 0, k;
		memset( data, 0, sizeof(data) );
		while( len >= Z10 ) {
			for( k = len - Z10; k < len; ++k ) data[i] = data[i] * 10 + buf[k] - '0';
			++i; len -= Z10;
		}
		if( len > 0 ) {
			for( k = 0; k < len; ++k ) data[i] = data[i] * 10 + buf[k] - '0';
		}
	}
	void  print() {
		int i;
		for( i = 5; i >= 0; --i ) if( data[i] > 0 ) break;
		if( i == -1 ) printf( "0" );
		else {
			printf( "%I64d", data[i] );
			for( --i; i >= 0; --i ) printf( "%018I64d", data[i] );
		}
		puts( "" );
	}
	void  convert( bigint_2t& dst );
private:
	LL  data[6];
};
class  bigint_2t {
	friend class bigint_10t;
public:
	bigint_2t() { memset( data, 0, sizeof(data) ); }
	void  assign( const LL x ) {
		memset( data, 0, sizeof(data) );
		data[0] = ( x & M2 ); data[1] = (x >> Z2);
	}
	void  assign( const bigint_2t& x ) {
		memcpy( data, x.data, sizeof(data) );
	}
	void  assign_sum( const bigint_2t& x, const bigint_2t& y ) {
		LL  carry = 0;
		for( int i = 0; i < 6; ++i ) {
			data[i] = y.data[i] + x.data[i] + carry;
			carry = (data[i] >> Z2);
			data[i] &= M2;
		}
	}
	void  add( const bigint_2t & x ) {
		LL  carry = 0;
		for( int i = 0; i < 6; ++i ) {
			data[i] = data[i] + x.data[i] + carry;
			carry = (data[i] >> Z2);
			data[i] &= M2;
		}
	}
	bool  operator <= ( const bigint_2t& x ) {
		for( int i = 5; i >= 0; --i ) {
			if( data[i] < x.data[i] ) return  true;
			else if( data[i] > x.data[i] ) return  false;
		}
		return  true;
	}
	bool  operator < ( const bigint_2t& x ) {
		for( int i = 5; i >= 0; --i ) {
			if( data[i] < x.data[i] ) return  true;
			else if( data[i] > x.data[i] ) return  false;
		}
		return  false;
	}
	void  get_fusc( bigint_10t& ans ) {
		bigint_10t  a, b;
		a.assign( 1 ); b.assign( 0 );
		int  i, j, k;
		for( j = 5; j > 0; --j ) if( data[j] > 0 ) break;
		for( i = 0; i < j; ++i ) {
			for( k = 0; k < Z2; ++k ) {
				if( data[i] & (1LL << k) ) b.add( a );
				else  a.add( b );
			}
		}
		LL  n = data[j];
		while( n ) {
			if( n & 1 ) b.add( a );
			else a.add( b );
			n >>= 1;
		}
		ans.assign( b );
	}
	void  muladd( const bigint_2t& x, LL a ) {
		LL  carry = 0;
		for( int i = 0; i < 6; ++i ) {
			data[i] = (x.data[i] << 1) + carry;
			carry = (data[i] >> Z2);
			data[i] &= M2;
		}
		data[0] += a;
	}
	void  print() {
		int i;
		for( i = 5; i >= 0; --i ) printf( "%I64d\n", data[i] );
	}
private:
	LL  data[6];
};
void  bigint_10t::convert( bigint_2t& dst ) {
	dst.assign( 0 );
	LL  h1, l1, h2 = ( M10 >> Z2H ), l2 = ( M10 & M2H ), tmp, q, r = 0;
	int  i = 5, j, k = 0;
	while( i >= 0 ) {
		while( data[i] == 0 ) --i;
		if( i < 0 ) break;
		for( r = 0, j = i; j >= 0; --j ) {
			h1 = r >> Z2H;  l1 = r & M2H;
			tmp = h1 * l2 + h2 * l1;
			q = h1 * h2 + ( tmp >> Z2H );
			r = ( ( tmp & M2H ) << Z2H ) + l1 * l2 + data[j];
			q += ( r >> Z2 );
			r &= M2;
			data[j] = q;
		}
		dst.data[k++] = r;
	}
}
struct  stat_t {
	int  start_a;
	int  start_b;
	int  start_c;
	void  assign( int a, int b, int c ) {
		start_a = a;
		start_b = b;
		start_c = c;
	}
};
bigint_2t  pos[42000];
int  cnt = 0;
stat_t  stat[334];
bigint_2t  xbeg[334];
bigint_2t  xend[334];
void  init() {
	int  i;
	xbeg[0].assign( 1 ); xend[0].assign( 1 );
	for( i = 1; i < 334; ++i ) {
		xbeg[i].muladd( xbeg[i-1], 0 );
		xend[i].muladd( xend[i-1], ( ( i & 1 ) ? 1 : -1 ) );
	}
	stat[0].assign( cnt, cnt, cnt ); pos[cnt++].assign( 1 );
	stat[1].assign( cnt, cnt, cnt ); pos[cnt++].assign( 3 );
	stat[2].assign( cnt, cnt, cnt ); pos[cnt++].assign( 5 );
	stat[3].assign( cnt, cnt, cnt + 1 ); pos[cnt++].assign( 9 ); pos[cnt++].assign( 11 );
	stat[4].assign( cnt, cnt, cnt + 1 ); pos[cnt++].assign( 19 ); pos[cnt++].assign( 21 );
	int  a, b, c, x, y;
	for( int lv = 5; lv < 334; ++lv ) {
		a = stat[lv-3].start_a; b = stat[lv-3].start_b; c = stat[lv-3].start_c;
		stat[lv].start_a = cnt; pos[cnt++].assign_sum( xbeg[lv], pos[a-1] );
		stat[lv].start_b = cnt;
		if( c - b > 2 ) x = ( lv & 1 ) ? c - 1 : c - 2;
		else x = ( c - b > 0 ) ? c - 1 : b;
		y = stat[lv-2].start_a;
		while( x < y ) pos[cnt++].assign_sum( xbeg[lv], pos[x++] );
		a = stat[lv-2].start_a; b = stat[lv-2].start_b; c = stat[lv-2].start_c;
		stat[lv].start_c = cnt;
		x = c - 1;
		y = stat[lv-1].start_a;
		while( x < y ) {
			if( (lv & 3) == 1 && x == y - 2 ) { ++x; continue; }
			pos[cnt++].assign_sum( xbeg[lv], pos[x++] );
		}
	}
}
int main() {
	int  t;
	bigint_10t  n, ans;
	bigint_2t   n2, one;
	one.assign( 1 );
	init();
	scanf( "%d", &t );
	while( t-- ) {
		n.read();
		n.convert( n2 );
		n2.add( one );
		lower_bound( pos, pos + cnt, n2 )[-1].get_fusc( ans );
		ans.print();
	}
	return 0;
}

Java代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
public class Nod1064 {
	public static void main(String[] args) throws Exception {
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				System.in), 1 << 16);
		int t = Integer.parseInt(reader.readLine());
		while (t-- > 0) {
			System.out.println(solve(new BigInteger(reader.readLine())));
		}
	}
	private static BigInteger solve(BigInteger n) {
		if (n.compareTo(BigInteger.ONE.shiftLeft(1)) <= 0) {
			return BigInteger.ONE;
		}
		if (n.bitCount() == 1) {
			n = n.subtract(BigInteger.ONE);
		}
		if (n.bitCount() == n.bitLength()) {
			return exFibnacc(BigInteger.ONE, BigInteger.ONE, n.bitLength() + 1);
		}
		int power = n.bitLength() - 1;
		return max(
				exFibnacc(BigInteger.ONE, BigInteger.ONE, power + 1),
				solve(BigInteger.ONE, BigInteger.ONE,
						n.subtract(BigInteger.ONE.shiftLeft(power)), power));
	}
	private static BigInteger solve(BigInteger left, BigInteger right,
			BigInteger index, int power) {
		if(index.bitCount() == 0) return left;
		if (index.bitLength() >= power) {
			if (left.compareTo(right) >= 0) {
				return exFibnacc(left, left.add(right), power + 1);
			} else {
				return max(
						exFibnacc(left, left.add(right), power + 1),
						solve(right.add(left), right, index
								.subtract(BigInteger.ONE.shiftLeft(power - 1)),
								power - 1));
			}
		} else {
			return solve(left, right.add(left), index, power - 1);
		}
	}
	private static BigInteger max(BigInteger a, BigInteger b) {
		return a.compareTo(b) > 0 ? a : b;
	}
	private static BigInteger exFibnacc(BigInteger first, BigInteger second,
			int n) {
		if(n == 1) return first;
		BigInteger temp = second;
		int size = n - 2;
		while(size-- > 0){
			temp = first.add(second);
			first = second;
			second = temp;
		}
		return temp;
	}

}

Python2代码:

import re
N = 400
f = []
def calc():
	global N
	global f
	f = [[0, 0] for i in xrange(N)]
	f[1][0] = 1
	f[1][1] = 0
	f[2][0] = 0
	f[2][1] = 1
	for i in xrange(3, N):
		f[i][0] = f[i - 1][0] + f[i - 2][0]
		f[i][1] = f[i - 1][1] + f[i - 2][1]
def bisearch(ll, rr, cc, lv, rv):
	global f
	global n
	mm = (ll + rr) / 2
	mv = lv + rv
	if mm <= n + 1:
		if cc == 1:
			ans = lv
		elif lv < mv:
			ans = lv * f[cc + 1][0] + mv * f[cc + 1][1]
		else:
			ans = mv * f[cc + 1][0] + lv * f[cc + 1][1]
		if ll < mm and n >= mm:
			ans = max(ans, bisearch(mm, rr, cc - 1, mv, rv))
	else:
		ans = bisearch(ll, mm, cc - 1, lv, mv)
	return ans
def solve():
	global f
	global n
	ll = 1
	cc = 0
	while (ll << 1) <= n:
		ll <<= 1
		cc += 1
	rr = ll << 1
	ans = f[cc + 1][0] + f[cc + 1][1]
	ans = max(ans, bisearch(ll, rr, cc, 1, 1))
	return ans
def main():
	calc()
	global n
	t = int(raw_input())
	for ti in xrange(t):
		n = int(raw_input())
		print(solve())
if __name__ == '__main__':
	main()

Python3代码:

import heapq, bisect
maxn = 10 ** 100
f = {0 : 0, 1 : 1}
def F(x) :
    if x in f :
        return f[x]
    if (x & 1) == 1 :
        f[x] = F(x >> 1) + F((x + 1) >> 1)
    else :
        f[x] = F(x >> 1)
    return f[x]
idx, val = [0], [F(0)]
que = [1]
while len(que) > 0 :
    u = heapq.heappop(que)
    fu = F(u)
    if val[-1] >= fu :
        continue
    idx += [u]
    val += [fu]
    v = (u << 1) - 1
    if v <= maxn :
        heapq.heappush(que, v)
    v = (u << 2) - 1
    if v <= maxn :
        heapq.heappush(que, v)
T = int(input())
for case in range(T) :
    n = int(input())
    i = bisect.bisect_right(idx, n)
    print(val[i - 1])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值