【HDU】4919 Exclusive or 推公式+高精度

本文详细解析了 HDU 4919 Exclusiveor 的求解思路,通过数学推导将问题转化为递推形式,并利用大数运算处理。通过分析奇偶数的异或特性,提出了一种高效的递推方法。

传送门:【HDU】4919 Exclusive or


题目分析:本题主要是要推出公式来。

这是叉姐给的题解,为什么可以这样呢?主要是因为奇数和偶数异或总可以转化为两个偶数的异或再加1,而奇数和奇数异或总可以转化为两个偶数的异或,然后对所有数除以二就可以得到子函数了。4k-4是因为1异或n-1等于0异或n-2,因为n=2k,且1异或n-1等于n-1异或1,所以得到4k-4。

而且这个式子有一个特殊性,就是推的过程中最多同时只存在两个相邻的子式(k和k+1或k-1和k)。所以可以递归或者递推。用一个包含两个元素的数组可以轻易表达,我们让第一个元素总为f(k)的值,那么第二个元素总为f(k+1)。用类似快速幂的方法递推就行了。

倒是大数写的吐血。。。为了赋值方便还用了vector。。。


代码如下:


#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
using namespace std ;
#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define max( a , b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
#define pb push_back

const int MAXN = 256 ;
const int L = 10000 ;

struct BigInt {
	int length , digit[MAXN] ;
	
	BigInt ( int number = 0 ) : length ( !!number ) {
		CLR ( digit , 0 ) ;
		digit[0] = number ;
		while ( length && digit[length - 1] >= L ) {
			digit[length] = digit[length - 1] / L ;
			digit[length - 1] %= L ;
			++ length ;
		}
	}
	
	BigInt fix () {
		while ( length && !digit[length - 1] )
			-- length ;
		return *this ;
	}
	
	int operator [] ( const int index ) const {
		return digit[index] ;
	}
	
	int & operator [] ( const int index ) {
		return digit[index] ;
	}
	
	BigInt operator = ( int number ) {
		CLR ( digit , 0 ) ;
		length = 0 ;
		while ( number ) {
			digit[length ++] = number % L ;
			number /= L ;
		}
		return *this ;
	}
	
	BigInt operator = ( const char *buf ) {
		CLR ( digit , 0 ) ;
		int len = strlen ( buf ) ;
		length = ( len -  1 ) / 4 + 1 ;
		REP ( i , 0 , len ) {
			int index = ( len - 1 - i ) / 4 ;
			digit[index] = digit[index] * 10 + buf[i] - '0' ;
		}
		return *this ;
	}
	
	BigInt operator + ( const BigInt &b ) const {
		BigInt c ;
		c.length = max ( ( *this ).length , b.length ) + 1 ;
		int add = 0 ;
		REP ( i , 0 , c.length ) {
			add += ( *this )[i] + b[i] ;
			c[i] = add % L ;
			add /= L ;
		}
		return c.fix () ;
	}
	
	BigInt operator - ( const int &b ) const {
		BigInt c ;
		c.length = ( *this ).length ;
		int del = -b ;
		REP ( i , 0 , ( *this ).length ) {
			del += ( *this )[i] ;
			c[i] = del ;
			del = 0 ;
			if ( c[i] < 0 ) {
				int tmp = ( -c[i] - 1 ) / L + 1 ;
				c[i] += tmp * L ;
				del = -tmp ;
			}
		}
		return c.fix () ;
	}
	
	BigInt operator * ( const BigInt &b ) const {
		BigInt c ;
		c.length = ( *this ).length + b.length ;
		REP ( i , 0 , ( *this ).length ) {
			int mul = 0 ;
			FOR ( j , 0 , b.length ) {
				mul += ( *this )[i] * b[j] + c[i + j] ;
				c[i + j] = mul % L ;
				mul /= L ;
			}
		}
		return c.fix () ;
	}

	BigInt operator / ( const int &b ) const {
		BigInt c ;
		c.length = ( *this ).length ;
		int over = 0 ;
		REV ( i , c.length - 1 , 0 ) {
			over = over * L + ( *this )[i] ;
			c[i] = over / b ;
			over %= b ;
		}
		return c.fix () ;
	}
	
	BigInt operator += ( const BigInt &b ) {
		*this = *this + b ;
		return *this ;
	}
	
	BigInt operator -= ( const int &b ) {
		*this = *this - b ;
		return *this ;
	}
	
	BigInt operator *= ( const BigInt &b ) {
		*this = *this * b ;
		return *this ;
	}
	
	BigInt operator /= ( const int &b ) {
		*this = *this / b ;
		return *this ;
	}
	
	bool operator < ( const BigInt &b ) const {
		if ( length != b.length )
			return length < b.length ;
		REV ( i , length - 1 , 0 )
			if ( digit[i] != b[i] )
				return digit[i] < b[i] ;
		return false ;
	}
	
	bool operator > ( const BigInt &b ) const {
		return b < *this ;
	}
	
	bool operator <= ( const BigInt &b ) const {
		return !( b < *this ) ;
	}
	
	bool operator >= ( const BigInt &b ) const {
		return !( *this < b ) ;
	}
	
	bool operator != ( const BigInt &b ) const {
		return b < *this || *this < b ;
	}
	
	bool operator == ( const BigInt &b ) const {
		return !( b < *this ) && !( *this < b ) ;
	}
} ;

char buf[500] ;

void print ( const BigInt &res ) {
	printf ( "%d" , res[res.length - 1] ) ;
	REV ( i , res.length - 2 , 0 )
		printf ( "%04d" , res[i] ) ;
	printf ( "\n" ) ;
}

BigInt calculate ( const BigInt &a , const BigInt &n ) {
	BigInt res ;
	if ( n[0] & 1 )
		res = n / 2 * 6 ;
	else
		res = n * 2 - 4 ;
	return res * a ;
}

void solve () {
	BigInt n , res = 0 ;
	n = buf ;
	std :: vector < BigInt > tmp ;
	tmp.pb ( 1 ) ;//n
	tmp.pb ( 0 ) ;//n + 1
	while ( n.length ) {
		res += calculate ( tmp[0] , n ) + calculate ( tmp[1] , n + 1 ) ;
		std :: vector < BigInt > new_tmp ;
		if ( n[0] & 1 ) {
			n /= 2 ;
			new_tmp.pb ( tmp[0] * 4 + tmp[1] * 2 ) ;//n / 2 - 1
			new_tmp.pb ( tmp[1] * 2 ) ;//n / 2
		}
		else {
			n = n / 2 - 1 ;
			new_tmp.pb ( tmp[0] * 2 ) ;//n / 2 - 1
			new_tmp.pb ( tmp[0] * 2 + tmp[1] * 4 ) ;//n / 2
		}
		tmp = new_tmp ;
	}
	print ( res ) ;
}

int main () {
	while ( ~scanf ( "%s" , buf ) )
		solve () ;
	return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值