zoukankan      html  css  js  c++  java
  • 牛客练习赛83 B. 计算几何(数位DP/找规律)

    链接:https://ac.nowcoder.com/acm/contest/11173/B
    来源:牛客网

    题目描述

    由于小 LL 追女孩子的时间不多了,于是这里只有简单版题意。

    共有 TT 组询问,每次给定 l,rl,r ,你需要求出在 [l,r][l,r] 中有多少个数在二进制下 11 的个数有奇数个。

    例如 4=(100)24=(100)2 ,在二进制下有 11 个 11 ,那么如果 l=r=4l=r=4 ,答案为 11 。

    例如 5=(101)25=(101)2 ,在二进制下有 22 个 11 ,那么如果 l=r=5l=r=5 ,答案为 00 。

    输入描述:

    第一行一个整数 TT 。接下来 TT 行,每行两个整数 l,rl,r 。
    

    输出描述:

    输出 TT 行,每行 11 个整数代表答案。
    

    示例1

    输入

    复制

    1
    3 4
    

    输出

    复制

    1
    

    说明

    (3)10=(11)2,(4)10=(100)2(3)10=(11)2,(4)10=(100)2 ,那么在 [3,4][3,4] 中只有 44 在二进制下有奇数个 11 。
    

    备注:

    1≤T≤10,1≤l≤r≤10181≤T≤10,1≤l≤r≤1018 。
    

    这个题可以打表找规律也可以推一下也可以数位dp一下,我选择数位dp。dp数组的含义是(dp[i][j][k])表示处理到第i位,之前是否紧贴边界,从第i位到第1位1的个数为奇数(k = 1) or 为偶数(k = 0)的数的个数。

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    int a, b, num[66], len;
    int dp[66][2][2];
    int dfs(int len, int flag, int odd_even) {//参数为从高到低当前处理到第几位 范围是1到len flag表示之前的部分是否紧贴边界 
    	//odd_even表示该状态后1的个数 为偶数0/为奇数1
    	if(len == 0) {
    		return 1;
    	}
    	if(dp[len][flag][odd_even] != -1) return dp[len][flag][odd_even];
     	int ans = 0;
    	for(int i = 0; i < 2; i++) {
    		if(!flag || (flag && i <= num[len])) {
    			if(i == 0) {
    				if(odd_even == 1) {
    					if(len != 1) ans += dfs(len - 1, flag && (i == num[len]), odd_even);//这一位为0,不改变之前1的奇偶个数
    					else ans += 0;
    				}
    				else if(odd_even == 0) {
    					if(len == 1) ans++;
    					else ans += dfs(len - 1, flag && (i == num[len]), odd_even);
    				}
    			} else {
    				if(odd_even == 0) {
    					if(len != 1) ans += dfs(len - 1, flag && (i == num[len]), 1);
    				}
    				else {	
    					if(len != 1) ans += dfs(len - 1, flag && (i == num[len]), 0);
    					else ans++;
    				}
    			}
    		}
    	}
    	return (dp[len][flag][odd_even] = ans);
    }
    int calc(int x) {
    	memset(num, 0, sizeof(num));
    	len = 0;
    	while(x) {
    		int now = x % 2;
    		x /= 2;
    		num[++len] = now;
    	}
    	for(int i = 0; i < 65; i++) {
    		for(int k = 0; k < 2; k++) {
    			for(int w = 0; w < 2; w++) {
    				dp[i][k][w] = -1;
    			}
    		}
    	}
    	int ret = dfs(len, 1, 1);
    	return ret;
    }
    signed main() {
    	int t;
    	cin >> t;
    	while(t--) {
    		cin >> a >> b;
    		cout << calc(b) - calc(a - 1) << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java JVM启动参数
    使用Navicat连接MySQL8.0版本报1251错误
    安装MySQL和出现的问题解决
    跨域问题:解决跨域的三种方案
    Java8 新特性lambda表达式(一)初始
    搭建docker私有仓库
    crontab定时任务
    CentOS610 php环境安装
    Docker常用命令
    PHP调用python脚本执行时报错
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14811309.html
Copyright © 2011-2022 走看看