zoukankan      html  css  js  c++  java
  • POJ 3252

    折腾了很久。

    注意到,每一个数总是这样的形式的:1010101100100。。

    如,当110000到111000时,我们可以看成是从110000到110111的计数。最后特判111000即可。这时,我们需要记下前三们110中1与0的个数之差,以决定后三位取0的个数。所以,不妨预处理出0,1,10,100,1000....等两数之间的ROUND数,再按上面说的按位计数即可。

    今天2015.2.7在做数位DP时又碰上这题了,重新写一写。

    举个例子,当1100000到1110000时,我们可以看成是从110000到110111的计数。最后特判111000即可。例如处理后三位的时候,这时我们需要记录下110这前三位0与1的个数的差-1,来决定后四位0与1的个数的差1。例如决定0比1多1时,这时可以运用组合数学的知识,那么只需在预出理出来的ROUND(所以,不妨预处理出0,1,10,100,1000....等两数之间的ROUND数,再按上面说的按位计数即可。)中,减去多于1的部分即可,。如果是K,则需要减去1~k部分。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define LL __int64
    using namespace std;
    
    LL pd[35];
    LL num[35];
    
    LL myc(int n,int r){
    	LL sum=1;
    	for(int i=1;i<=r;i++)
    	sum=sum*(LL)(n+1-i)/(LL)i;
    	return sum;
    }
    
    void initial(){
    	pd[0]=1; 
    	pd[1]=0; 
    	LL tmp,sum;
    	int r;
    	for(int i=2;i<=33;i++){
    		r=(i-1)/2+1;
    		tmp=myc(i-1,r);
    		pd[i]=tmp;
    		for(int j=r+1;j<=i-1;j++){
    			tmp=tmp*(LL)(i-1-j+1)/(LL)j;
    			pd[i]+=tmp;
    		}
    	}
    }
    
    LL how(LL as){
    	LL ret=0;
    	while(as){
    		ret++;
    		as=(as>>1);
    	}
    	return ret;
    }
    
    LL ABS(LL a){
    	return a>=0?a:-a;
    }
    
    LL confer(LL as,LL bt,int pos){
    	LL res=0;
    	for(LL i=0;i<bt;i++)
    	res+=pd[i];
    	LL ans=1;
    	LL tmp=(1LL<<(bt-2));
    	LL r;
    	for(LL i=bt-1;i>0;i--){
    		if(tmp&as){
    			ans++;
    		}
    		else ans--;
    		if(tmp&as){
    		//	if(i-1==0) continue;
    			if(ans-2>=0){
    				r=(ans-2+i-1);
    				if(r%2) r=r/2+1;
    				else r=r/2;
    			}
    			else{
    				r=i-1-(ans-2);
    				if(r%2) r=r/2+1;
    				else r=r/2;
    				r=r-ABS(ans-2);
    				if(r<=0) r=0;
    			}
    			LL sum=myc((int)i-1,(int)r);
    			res+=sum;
    			for(LL k=r+1;k<=i-1;k++){
    				sum=sum*(i-k)/k;
    				res+=sum;
    			}
    		}
    		tmp>>=1;
    	}
    	if(ans<=0&&pos==2) res++;
    	return res;
    }
    
    int main(){
    	initial();
    	LL a,b;
    	while(scanf("%I64d%I64d",&a,&b)!=EOF){
    		LL bta=how(a),btb=how(b);
    		bta=confer(a,bta,1);
    	//	cout<<bta<<endl;
    		btb=confer(b,btb,2);
    		printf("%I64d
    ",btb-bta);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Mysql 数据库 表中列的操作
    FreeSWITCH版本更新
    shell脚本58问
    Wireshark 与 Tcpdump
    Mysql 中 int(3) 和 int(11) 的区别
    FreeSWITCH 基础
    FreeSWITCH 学习笔记(一)
    Mysql 复制表数据(表结构相同)
    Centos date 设置自定义时间
    Mysql 主键
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3992998.html
Copyright © 2011-2022 走看看