题目分析:本题主要是要推出公式来。
这是叉姐给的题解,为什么可以这样呢?主要是因为奇数和偶数异或总可以转化为两个偶数的异或再加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 ;
}