BUPT Summer Journey #test4 D

時間限制 1000 ms內存限制65536 KB

題目描述

崔逗逗是一個善良的學長,最喜歡爲學弟學妹出水題。他給大家一個整數n,求0<=x<=n的範圍內,有多少個數滿足(x)^(2x)^(3x)==0 (^是異或符號)。你只要告訴他對1000000009取餘的答案就好啦。

輸入格式

輸入有多組數據,數量在100以內,每行一個整數n(0<=n<=10^18)。

輸出格式

每組數據輸出一行答案。

輸入樣例

1
2

輸出樣例

2
3
思路:

首先,亦或是與一個數的二進制表示有關,轉化爲二進制後,由x^(2x)==3x和x+(2x)==3x知,畫出圖來發現對於一個數,相鄰的數不能爲1,設相鄰的數L位的總數爲f(L),不難發現,若最後一位爲0,前面L-1變成了一個子問題f(L-1),若最後一位爲1,倒數第二位可1可0,前面L-2變成了一個子問題f(L-2),初始化f(0)=1,f(1)=2,則轉化爲一個二進制數與f(L)的關係,我們可以先求出L-1的最大表示1111...1,然後從倒數第二位開始遞推,若該位爲1,則該位爲0的前面i-1爲子問題f(i-1),並記錄前驅,若不滿足了則跳出。

代碼:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define MOD 1000000009
using namespace std;
long long n,ans;
int bit[100],f[100],referbit[100];
int main()
{
    f[0]=1;f[1]=2;
    for(int i=2;i<=70;i++)f[i]=(f[i-1]+f[i-2])%MOD;
    while(scanf("%lld",&n)==1)
    {
        if(n==0){printf("1\n");continue;}
        memset(bit,0,sizeof(bit));
        //memset(referbit,0,sizeof(bit));
        while(n)
        {
            bit[0]++;
            bit[bit[0]]=n%2;
            n/=2;
        }
        int pre=1,i;ans=f[bit[0]-1];
        for(i=bit[0]-1;i>=1;i--)
        {
            if(bit[i]==0){pre=0;continue;}
            if(bit[i]==1)
            {
                ans=ans+f[i-1];
                if(pre==1)break;
                else pre=1;
            }
        }
        if(i==0)ans=(ans+1)%MOD;
        printf("%lld\n",ans%MOD);
    }
    return 0;
}
/*
a[0]=1
a[1]=2
a[2]=3
a[3]=3
a[4]=4
a[5]=5
a[6]=5
a[7]=5
a[8]=6
a[9]=7
a[10]=8
a[11]=8
a[12]=8
a[13]=8
a[14]=8
a[15]=8
a[16]=9
a[17]=10
a[18]=11
a[19]=11
a[20]=12
a[21]=13
a[22]=13
a[23]=13
a[24]=13
a[25]=13
a[26]=13
a[27]=13
a[28]=13
a[29]=13
a[30]=13
a[31]=13
a[32]=14
*/





 

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