POJ 3252 递推关系

来源:互联网 发布:30岁的程序员何去何从 编辑:程序博客网 时间:2024/05/16 02:10

2015/2/19


递推。

给定一个区间内有多少个数,数的二进制中0的数量不比1少。

范围决定不能暴力(显而易见的)


利用递推求区间和的方式 

区间【L, R】 -> 最后的形式是 Sum(R) - Sum(L - 1)


问题来了,如何求Sum(X)?


我选择的方式是,

输入N, M  ,(以N为例) 把N转换成二进制 len为N 的二进制长度。

递推  (1 ~  len )位数的二进制数中满足条件的数有几个。

比如:2进制 2位数 中满足题目的数只有一个 10.       4位数 4个  1000 1001 1100 1010(然后去组合数学吧)这部分可以打表

然后麻烦的地方在于  10  ->  1010  ,如果你把i = 4 的情况算进去 ,那么有1100   符合算法    却不符合题意 1100-12 >10 ;

所以i  = len 的情况还要独自考虑下。

遍历二进制数,从高位往低位,遇到1即可将其变成0,然后在计算下 1->0的时候之前位上的变化有几种。

反正很烦就对了(你打我呀)。

#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#include<climits>#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;  #define mod 10007#define lson pos<<1,l,mid#define sc(n) scanf("%d",&n)#define rson pos<<1|1,mid+1,r#define pr(n) printf("%d\n",n)#define met(n,m) memset(n, m, sizeof(n))#define F(x,y,i) for(int i = x;i > y; i--)#define f(x,y,i) for(int i = x;i < y; i++)#define ff(x,y,i) for(int i = x;i <= y; i++)#define FF(x,y,i) for(int i = x;i >= y; i--) const int N=100500;const int inf = INT_MAX;int Max(int a,int b){return a>b?a:b;}int Min(int a,int b){return  a<b?a:b;}int a1[1005],a2[1005];int ans[35];int turn(int x,int y){__int64 sum = 1;__int64 dum = 1;__int64 nnm = 1;f(0, y , i){nnm *=(x  - i);dum *= i+1;}return (int)(nnm/dum) ;}int turn_0(int x){int num = x/2 - 1;__int64 sum = 1;__int64 dum = 1;__int64 nnm = 1;f(0, num , i){nnm *=(x -1 - i);dum *= i + 1;sum+=nnm/dum;}return (int)(sum);}int main()  {       int n, m, tot, x; ans[0] = ans[1] = 0;  f(2,35,i) { ans[i] = turn_0(i); } f(2,35,i)ans[i] += ans[i-1];      while(~scanf("%d%d",&m,&n))    {    int cnt1 = 0,cnt2 = 0;    int sum1 = 0,sum2 = 0;    int one1 = 0,one2 = 0;          while(n)  {    a1[cnt1++] = n%2;  if(a1[cnt1-1])one1++;  n/=2;    }     m--;while(m){a2[cnt2++] = m%2;if(a2[cnt2-1])one2++;m/=2;} sum1 = ans[cnt1-1];sum2 = ans[cnt2-1];if(cnt1>1&&cnt1 >= one1*2)sum1++;if(cnt2>1&&cnt2 >= one2*2)sum2++;  f(0,cnt1-1,i) { if(a1[i]) { one1--;   if(cnt1 >= one1*2)sum1++;   int num = cnt1/2 - one1;  num = Min(num,i);  f(1,num+1,j) { sum1 += turn(i,j); }  } }   f(0,cnt2-1,i) { if(a2[i]) { one2--;  int num = cnt2/2 - one2;  if(cnt2 >= one2*2)sum2++;  num = Min(num,i);  f(1,num+1,j) { sum2 += turn(i,j); }  } } printf("%d\n",sum1 - sum2);          }    return 0;  }  



0 0