hdu 4919 Exclusive or

Exclusive or

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 377    Accepted Submission(s): 159


Problem Description
Given n, find the value of 


Note: ⊕ denotes bitwise exclusive-or.
 

Input
The input consists of several tests. For each tests:

A single integer n (2≤n<10 500).
 

Output
For each tests:

A single integer, the value of the sum.
 

Sample Input
      
      
3 4
 

Sample Output
      
      
6 4
 

Author
Xiaoxu Guo (ftiasch)
 

Source
 

Recommend
We have carefully selected several similar problems for you:   4920  4919  4918  4917  4916 
 

公式题解已经给出了,貌似有网站上可以直接搜到那个公式:

if(n<2)
    return 0;
   if(n%2==0)
    return 2*a(n/2)+2*a(n/2-1)+4*(n/2-1);
   else return 4*a((n-1)/2)+6*((n-1)/2);

不过这题数据很大,建议用Java写,因为Java里面在记忆化搜索时存数据要方便很多,而因为这题不用记忆化搜索的话,很容易超时,

import java.util.*;
import java.math.BigInteger;

public class Main {
	public static HashMap<BigInteger, BigInteger> map = new HashMap<BigInteger, BigInteger>();
	public static BigInteger fun(BigInteger x)
	{
		if(map.containsKey(x))
			return map.get(x);
		BigInteger temp,next,next2,ans;
		temp = BigInteger.valueOf(2);
		next = x.divide(temp);
		next2 = x.add(BigInteger.ONE.negate());
		next2 = next2.divide(temp);
		if(x.compareTo(BigInteger.valueOf(2))<0)
			return BigInteger.ZERO;
		if(x.mod(temp).compareTo(BigInteger.ZERO)==0)
			ans = temp.multiply(fun(next)).add(temp.multiply(fun(next.add(BigInteger.ONE.negate())))).add(next.add(BigInteger.ONE.negate()).multiply(BigInteger.valueOf(4)));
		else ans = BigInteger.valueOf(4).multiply(fun(next2)).add(BigInteger.valueOf(6).multiply(next2));
		map.put(x, ans);
		return ans;
	}
	public static void main(String[] agrs)
	{
		Scanner cin = new Scanner(System.in);
		BigInteger n;
		while(cin.hasNext())
		{
			n = cin.nextBigInteger();
			System.out.println(fun(n));
		}
		cin.close();
		
	}
}
下面是C++大数写的,不过没加记忆化,T了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<time.h>
#include<math.h>
#include<algorithm>
#define MM 1000000000
using namespace std;

struct Bignum{
    __int64 dig[60];
    int len;
    void clean()
    {
        memset(dig,0,sizeof(dig));
        len=1;
    }
    void print(bool flag=false)
    {
        int i=len-1;
        printf("%I64d",dig[i]);
        for(i--;i>=0;i--)
            printf("%09I64d",dig[i]);
        if(flag)
            printf("\n");
    }
};

Bignum zero,one;

Bignum add(Bignum a,Bignum b) //大数的加法模版
{
    if(b.len>a.len)
        a.len=b.len;
    for(int i=0;i<a.len;i++)
    {
        a.dig[i] += b.dig[i];
        if(a.dig[i]>=MM)
        {
            a.dig[i] -= MM;
            a.dig[i+1]++;
        }
        if(a.dig[a.len]>0)
            a.len++;
    }
    return a;
}

Bignum cut(Bignum a,Bignum b) //大数的减法模版,只考虑a大于b的情况
{
    for(int i=0;i<a.len;i++)
    {
        a.dig[i] -= b.dig[i];
        if(a.dig[i]<0)
        {
            a.dig[i] += MM;
            a.dig[i+1]--;
        }
        while(a.len>1&&!a.dig[a.len-1])//
            a.len--;
    }
    return a;
}

Bignum multi(Bignum a,__int64 b) //大数与__int64的乘法模版
{
    for(int i=0;i<a.len;i++)
        a.dig[i] *= b;
    for(int i=0;i<a.len;i++)
        if(a.dig[i]>=MM)
        {
            a.dig[i+1] += a.dig[i]/MM;
            a.dig[i] %= MM;
        }
    while(a.dig[a.len]>0)
    {
        a.dig[a.len+1] += a.dig[a.len]/MM;
        a.dig[a.len] %= MM;
        a.len++;
    }
    return a;
}

Bignum multi(Bignum a,Bignum b)//两个大数的乘法运算(很经典)
{
    int i,j;
    __int64 d;
    Bignum c;c.clean();
    c.len=a.len+b.len;
    for(i=0;i<a.len;i++)
        for(j=0;j<b.len;j++)
    {
        d=a.dig[i]*b.dig[j];
        c.dig[i+j+1] += (d + c.dig[i+j])/MM;
        c.dig[i+j] = (d+ c.dig[i+j])%MM;
    }
    if(!c.dig[c.len-1])//
        c.len--;
    return c;
}

Bignum division(Bignum a,__int64 b) //大数的除法模版
{
    for(int i=a.len-1;i>0;i--)//此循环i不能等于0
    {
        a.dig[i-1] += a.dig[i]%b*MM;
        a.dig[i] /= b;
    }
    a.dig[0] /= b;
    while(a.len>1&&!a.dig[a.len-1])
    {
        a.len--;
    }
    return a;
}

int  cmp(Bignum a,Bignum b) //比较两个大数的大小
{
        if(a.len>b.len)
            return 1;
        else if(a.len<b.len)
            return -1;
        for(int i=a.len-1;i>=0;i--)
            if(a.dig[i]!=b.dig[i])
                return a.dig[i]-b.dig[i];
        return 0;
}

Bignum intchange(__int64 s)//将一个__int64类型的树转化成大数
{
    Bignum c;
    c.clean();
    int i=0;
    if(!s)   return c;
    while(s>0)
    {
        c.dig[i++] = s%MM;
        s /= MM;
    }
    c.len=i;
    return c;
}

Bignum charchange(char s[])//将字符串转换成大数
{
    Bignum c;c.clean();
    int i,j,k=0,L=strlen(s);
    __int64 p;
    for(i=L-1;i>=0;)
    {
        p=1;
        for(j=0;j<9&&i>=0;j++,i--)
        {
            c.dig[k] += p*(s[i]-'0');
            p *= 10;
        }
        k++;
    }
    c.len=k;
    return c;
}

__int64 bigmod(Bignum a,__int64 s)//大数取余
{
    int i;
    __int64 mod=MM%s,ret;
    for(i=a.len-1;i>=0;i--)
    {
        ret = (ret*mod+a.dig[i])%s;
    }
    return ret;

}

Bignum sove(Bignum x)
{
    Bignum temp,next;
    temp = intchange(2);
    next = division(x,2);
    if(cmp(x,temp)<0)
        return zero;
    if(bigmod(x,2)==0)
        return add(multi(temp,add(sove(next),sove(cut(next,one)))),multi(cut(next,one),4));
    //return 2*a(n/2)+2*a(n/2-1)+4*(n/2-1);
    else return add(multi(sove(division(cut(x,one),2)),4),multi(division(cut(x,one),2),6));
   //else return 4*a((n-1)/2)+6*((n-1)/2);
}

int main()
{
    char s[550];
    Bignum n,ans;
    zero.clean();
    one.clean();
    one.dig[0]++;
    while(~scanf("%s",s))
    {
        n = charchange(s);
        ans = sove(n);
        ans.print();
        cout<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值