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<10500).
 

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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章