435. 崔逗逗给你信心
时间限制 1000 ms
内存限制 65536 KB
题目描述
崔逗逗是一个善良的学长,最喜欢为学弟学妹出水题。他给大家一个整数n,求0<=x<=n的范围内,有多少个数满足(x)^(2x)^(3x)==0 (^是异或符号)。你只要告诉他对1000000009取余的答案就好啦。
输入格式
输入有多组数据,数量在100以内,每行一个整数n(0<=n<=10^18)。
输出格式
每组数据输出一行答案。
输入样例
1
2
输出样例
2
3
分析:(i^(2*i)^(3*i))==0 --- i^(2*i)==3*i==i+2*i--- 2*i相当于把i左移1位,当且仅当没有相邻1时,相加与异或等价。
不考虑大小,二进制n位数中满足条件的个数为f(n),满足f(n)=f(n-1)+f(n-2)
然后考虑小于n的数,首先,最高位取0,sum+=f(len-1)
最高位取1,考虑次高位,如果次高位为1,sum+=f(len-2)
次高位为0,则往后扫描到最高1,递归求解。
代码:#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<stack> #define MOD 1000000009 using namespace std; long long f[100]; long long sum; int num[100]; void get(int len) { if(len==1&&num[0]==1) sum+=2; else { sum=(sum+f[len-1])%MOD; if(len>=2) { if(num[len-2]==1) sum=(sum+f[len-2])%MOD; else { int j=len-2; while(j>=0&&num[j]==0) j--; if(j<0) { sum=(sum+1)%MOD; } else get(j+1); } } } } int main() { long long n,i; int len; f[0]=1;f[1]=2;f[2]=3; for(i=3;i<100;i++) { f[i]=(f[i-1]+f[i-2])%MOD; } while(scanf("%lld",&n)!=EOF) { sum=0; if(n==0) printf("1\n"); else { len=0; while(n) { num[len]=n%2; n>>=1; len++; } get(len); printf("%lld\n",sum); } } return 0; }