CodeForces - 611B 数学思维
2016-12-10 20:04
417 查看
The year 2015 is almost over.
Limak is a little polar bear. He has recently learnt about the binary system. He noticed that the passing year has exactly one zero in its representation in the binary system — 201510 = 111110111112.
Note that he doesn't care about the number of zeros in the decimal representation.
Limak chose some interval of years. He is going to count all years from this interval that have exactly one zero in the binary representation. Can you do it faster?
Assume that all positive integers are always written without leading zeros.
Input
The only line of the input contains two integers a and b (1 ≤ a ≤ b ≤ 1018) — the first year and
the last year in Limak's interval respectively.
Output
Print one integer – the number of years Limak will count in his chosen interval.
Example
Input
Output
Input
Output
Input
Output
Input
Output
Hint
In the first sample Limak's interval contains numbers 510 = 1012, 610 = 1102, 710 = 1112,810 = 10002, 910 = 10012 and 1010 = 10102.
Two of them (1012 and 1102) have the described property.
题意:就是让你找出给定区间里各个数的二进制中只有一个0的数有多少个;
思路:对于这个题我就单纯的找规律,我们可以发现:
当二进制有两位时 只有1种
当二进制有三位时 只有2种
当四位 3种
五位 4种
由此可以发现这个规律是一个等差数列,那么我们就想可不可以求出给定的区间(a,b)中从(0,a)有多少个,从(0,b]有多少个,两个数做差就为[a,b]的个数;
那么对于给定的数x 他的二进制位数为k,我们找到它二进制中出现第一个0的位置,然后依次将它前面的 1变0将第一个0变为1,就可以找到当二进制位数为k时小于x的满足题意的个数.
这里我来说明一下为什么只需要找到它二进制的第一个0然后变前面不变后面呢?因为我们要求的是区间(0,b]中满足题意的,我们如果变后面的话就会将这个数变大超过b,我们要将这个数变小,就要变高位的1,自己体会一下就明白了;
注意对于区间右面的端点我们需要判断其本身是不是,而左端点不需要;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
int s1[10000],s2[10000];
ll a,b;
int main()
{ cin>>a>>b;
ll k=0,ans1=0,ans2=0,i,j;
while(a)
{ s1[k++]=a%2;
a>>=1;
}
for(j=k-1;j>=0;j--)
{ if(s1[j]==0)
break;
}
if(k>=3)
{ ans1=((k-1)*(k-2))/2;
}
else
ans1=0;
if(k-j-2>=1&&j>=0)
ans1+=k-j-2;
else if(j<0)
ans1+=k-1;
k=0;
while(b)
{ s2[k++]=b%2;
b>>=1;
}
for(i=k-1;i>=0;i--)
{ if(s2[i]==0)
break;
}
if(k>=3)
{ ans2=((k-1)*(k-2))/2;
}
else
ans2=0;
if(k-i-2>=1&&i>=0)
ans2+=k-i-2;
else if(i<0)
ans2+=k-1;
for(j=0;j<k;j++)
{ if(s2[j]==0)
break;
}
if(j==i)
printf("%lld\n",ans2-ans1+1);
else
printf("%lld\n",ans2-ans1);
return 0;
}
Limak is a little polar bear. He has recently learnt about the binary system. He noticed that the passing year has exactly one zero in its representation in the binary system — 201510 = 111110111112.
Note that he doesn't care about the number of zeros in the decimal representation.
Limak chose some interval of years. He is going to count all years from this interval that have exactly one zero in the binary representation. Can you do it faster?
Assume that all positive integers are always written without leading zeros.
Input
The only line of the input contains two integers a and b (1 ≤ a ≤ b ≤ 1018) — the first year and
the last year in Limak's interval respectively.
Output
Print one integer – the number of years Limak will count in his chosen interval.
Example
Input
5 10
Output
2
Input
2015 2015
Output
1
Input
100 105
Output
0
Input
72057594000000000 72057595000000000
Output
26
Hint
In the first sample Limak's interval contains numbers 510 = 1012, 610 = 1102, 710 = 1112,810 = 10002, 910 = 10012 and 1010 = 10102.
Two of them (1012 and 1102) have the described property.
题意:就是让你找出给定区间里各个数的二进制中只有一个0的数有多少个;
思路:对于这个题我就单纯的找规律,我们可以发现:
当二进制有两位时 只有1种
当二进制有三位时 只有2种
当四位 3种
五位 4种
由此可以发现这个规律是一个等差数列,那么我们就想可不可以求出给定的区间(a,b)中从(0,a)有多少个,从(0,b]有多少个,两个数做差就为[a,b]的个数;
那么对于给定的数x 他的二进制位数为k,我们找到它二进制中出现第一个0的位置,然后依次将它前面的 1变0将第一个0变为1,就可以找到当二进制位数为k时小于x的满足题意的个数.
这里我来说明一下为什么只需要找到它二进制的第一个0然后变前面不变后面呢?因为我们要求的是区间(0,b]中满足题意的,我们如果变后面的话就会将这个数变大超过b,我们要将这个数变小,就要变高位的1,自己体会一下就明白了;
注意对于区间右面的端点我们需要判断其本身是不是,而左端点不需要;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
int s1[10000],s2[10000];
ll a,b;
int main()
{ cin>>a>>b;
ll k=0,ans1=0,ans2=0,i,j;
while(a)
{ s1[k++]=a%2;
a>>=1;
}
for(j=k-1;j>=0;j--)
{ if(s1[j]==0)
break;
}
if(k>=3)
{ ans1=((k-1)*(k-2))/2;
}
else
ans1=0;
if(k-j-2>=1&&j>=0)
ans1+=k-j-2;
else if(j<0)
ans1+=k-1;
k=0;
while(b)
{ s2[k++]=b%2;
b>>=1;
}
for(i=k-1;i>=0;i--)
{ if(s2[i]==0)
break;
}
if(k>=3)
{ ans2=((k-1)*(k-2))/2;
}
else
ans2=0;
if(k-i-2>=1&&i>=0)
ans2+=k-i-2;
else if(i<0)
ans2+=k-1;
for(j=0;j<k;j++)
{ if(s2[j]==0)
break;
}
if(j==i)
printf("%lld\n",ans2-ans1+1);
else
printf("%lld\n",ans2-ans1);
return 0;
}
相关文章推荐
- CodeForces - 899D Shovel Sale 数学+思维
- CodeForces 626B Cards(数学思维)
- 【Codeforces-402B】-Weird Rounding(数学,思维)
- CodeForces - 540B School Marks (数学思维题 中位数)
- 【CodeForces 804B】Minimum number of steps(思维+数学)
- 【数学思维】CodeForces - 233B Non-square Equation
- Codeforces 702D Road to Post Office【捎带数学的思维题】
- CodeForces 876B Divisiblity of Differences(思维 + 数学)
- codeforces 936A Save Energy(数学思维)
- 【组合数学思维】CodeForces - 233C Cycles
- Codeforces 233B Non-square Equation (数学+思维)
- Codeforces 570B Simple Game 概率求解,简单数学思维
- Codeforces400E - Inna and Binary Logic - 思维、数学
- Codeforces 807C Success Rate【二分+数学思维】
- Codeforces 758C Unfair Poll 【数学】【思维】
- 【Codeforces 869 C The Intriguing Obsession】& 组合数学 & 思维
- codeforces 560C Gerald's Hexagon (数学+思维)
- Codeforces 789A Anastasia and pebbles(数学,思维题)
- Codeforces-448【A数学函数ceil】【B思维】【D二分】
- 51nod 1421 最大MOD值 & codeforces 485D Maximum Value(思维 数学)