• 洛谷P6218


    感觉此题是P4317 花神的数论题的变形版


    Description

    求一段区间内二进制中 (0) 的个数不小于 (1) 的个数的数的个数


    Solution

    数位 DP

    先考虑状态转移方程式,如何处理处所有数

    (f[i][j][k]) 表示枚举到第 (i) 位,数字为 (j),此时二进制中 (1) 的个数为 (k)

    显然有

    [f[i][0][j]=sum_{k=0}^if[i-1][1][k]+f[i-1][0][k] ]

    [f[i][1][j]=sum_{k=1}^if[i-1][0][k-1]+f[i-1][1][k-1] ]

    与花神的数论题是一样的

    另一部分,考虑答案的统计

    显然,对于 (ans_{l,r}),可以转化为 (ans_{1,r}-ans_{1,l-1})

    把最高位上的数与最高位以下的分开统计

    由于存在原数定义的限制,我们对于 (ans_{1,V}) 可用如下方法处理

    (len)(V) 的位数, (a_i)(V) 的第 (i)

    对于首位为 (1) 且前面有 (cnt1)(1)(f)

    (res+=f[i][0][j],iin[1,len),jin[0,len/2-cnt1])

    对于首位为 0 的 f,

    (res+=f[i][1][j],iin[1,len),jin[0,i/2])


    Code

    #include<cstdio>
    #include<iostream>
    #include<cstring> 
    #include<cmath>
    #include<algorithm>
    #define maxn 10000100	
    //#define int long long
    
    using namespace std;
    
    int f[50][2][50],a[50];
    int l,r;
    
    int read(){
    	int s=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
    	return s*w;
    }
    
    void init(){
    	f[1][1][1]=1;f[1][0][0]=1;
    	for(int i=2;i<35;i++)
    		for(int j=0;j<=1;j++)
    			for(int k=0;k<=i;k++)
    				for(int s=0;s<=1;s++){
    					if(!j)f[i][j][k]+=f[i-1][s][k];
    					if(j&&k) f[i][j][k]+=f[i-1][s][k-1];
    				}
    }
    
    int solve(int x){
    	memset(a,0,sizeof a);
    	int len=0,ans=0,cnt1=1,cnt0=0;
    	while(x){a[++len]=x%2;x/=2;}
    	for(int i=len-1;i>=1;i--){
    		if(a[i]) for(int j=0;j<=len/2-cnt1;j++) ans+=f[i][0][j];
    		cnt1+=a[i];cnt0+=(a[i]==0);
    		if(cnt0>=cnt1&&i==1) ans++;
    	}
    	for(int i=1;i<len;i++)
    		for(int j=0;j<=i/2;j++)
    		    ans+=f[i][1][j];
    	return ans;
    }
    
    int main(){
    	init();
    	l=read();r=read();
    	printf("%d",solve(r)-solve(l-1));
    	return 0;
    }
    

  • 相关阅读:
    51Nod1528 加号分配
    51Nod1679 连通率
    51Nod1679 连通率
    51Nod1426 沙拉酱括号
    51Nod1426 沙拉酱括号
    51Nod1678 lky与gcd
    51Nod1556 计算
    c学习第2天
    Stopwatch秒表的使用
    数据从.txt文件中导入数据库
  • 原文地址:https://www.cnblogs.com/KnightL/p/14144104.html
Copyright © 2020-2023  润新知