转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1301472836
不懂看这篇博客吧。
排列组合模版用这个吧,现在来看,似乎代码中的排列组合模版容易溢出
__int64 C(__int64 m, __int64 n){
if(m > n - m) m = n - m;
__int64 ans = 1, cou = m;
while(cou --){
ans *= n --;
while(ans % m == 0 && m > 1)
ans /= m --;
}
return ans;
}
//164k 0ms
#include <iostream>
using namespace std;
#define MAX 35
int a[MAX]; //存储二进制长度为i时的round number
__int64 C(int a, int b) //排列组合
{
__int64 ans;
if(!a)
ans = 1;
else
{
if(b - a < a)
a = b - a;
int i;
__int64 m = 1,n = 1;
for(i = 1; i <= a; i++)
{
n *= i;
m *= b + 1 - i;
}
ans = m / n;
}
return ans;
}
void makeMap()
{
int i, j;
a[1] = 0;
for(i = 2; i < MAX; i++) //i表示二进制长度且二进制最后一位为1
{
a[i] = 0;
for(j = 1; j <= i-j; j++) //j表示二进制表示中1的个数
a[i] += C(j-1,i-1);
}
}
int cal(int m) //计算0到m之间的round number
{
int len = 0, binary[MAX];
for(; m != 0; m /= 2)
binary[len++] = m % 2;
int i, j, ans = 0, b = 1, c = 0; //b和c分别存储1和0的个数,由于二进制序列的最后一位必须为1,所以b初始化为1
for(i = 1; i < len; i++) // 计算长度小于len时的round number
ans += a[i];
//printf("%d***\n", ans);
for(i = len-2; i >= 0; i--) // 计算长度为len时的round number
if(binary[i])
{
for(j = 0; j <= i && b + j <= len - b - j; j++)
{
ans += C(j, i);
//printf("\n%d***\n", ans);
}
b++;
}
else c++;
return ans;
}
int main()
{
int sta, fin;
scanf("%d%d", &sta, &fin);
makeMap();
printf("%d\n", cal(fin+1)-cal(sta));
return 0;
}