[UVALive3675]Sorted bit sequence && 数位DP

本文介绍了一种利用二分查找与组合数学的方法来解决特定类型的问题,特别是涉及区间内二进制数中1的个数的问题。通过预先计算组合数并使用二分查找技术,可以在较短时间内定位到特定排名的数值。

我被开区间坑了啊!! 其实闭区间也不错 闭区间是INI_MAX 加个1变成开区间溢出了 坑死个人了= = 


主要思路 

首先要确定目标有多少个1 就把1的个数为0 1 2 的加起来 什么时候超过k了 就停止 这样就确定了1的个数

然后需要在这些数里找到目标 方法是二分 然后就没有然后了


负数先忽略最高位的1 然后搞完再把符号弄回来就行了 

还有就是边界值为0的时候需要有一些特殊讨论 总之到处是坑啊 


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned int uint;
const int MAXN = 32;
int d[MAXN+10][MAXN+10], bit[MAXN+10];
void init()
{
	for(int i = 0; i <= MAXN; i++) d[i][0] = 1;
	for(int i = 1; i <= MAXN; i++)
		for(int j = 1; j <= i; j++)
			d[i][j] = d[i-1][j] + d[i-1][j-1];
}
LL cal(int x, int k)
{
	int Len = 0; LL ans = 0;
	memset(bit, 0, sizeof(bit));
	while(x) {
		bit[++Len] = x & 1;
		x >>= 1;
	}
	for(int i = Len; i >= 1; i--)
		if(bit[i])
		{
			if(k < 0) break;
			ans += d[i-1][k];
			k--;
		}
	if(!k) ans++;
	return ans;
}
bool check(int L, int R, int k, int rank)
{
	int tmp = cal(R, k) - cal(L-1, k);
	return tmp >= rank;
}
int solve(int L, int R, int x)
{
	int i, st = L;
	for(i = 1; i <= MAXN; i++)
	{
		LL tmp = cal(R, i) - cal(L-1, i);
		if(tmp < x) x -= tmp;
		else break;
	}
	while(L < R)
	{
		int mid = ((LL)L + R) >> 1;
		if(check(st, mid, i, x))
			R = mid;
		else 
			L = mid+1;
	}
	return L;
}
int main()
{
	init();
	int T; scanf("%d", &T); while(T--) {
		int L, R, K;
		scanf("%d%d%d", &L, &R, &K);
		if(R > 0) {
			if(L == 0 && K == 1)  { printf("0\n"); continue; }
			if(L == 0) L++, K--;
			int ans = solve(L, R, K);
			printf("%d\n", ans);
		}
		else {
			if(R == 0 && K == 1)  { printf("0\n"); continue; }
			if(R == 0) R--, K--;
			int flag = R < 0;
			L = (uint)L & (((uint)1 << 31) - 1);
			R = (uint)R & (((uint)1 << 31) - 1);
			if(R == 0) {
				if(K == 1) { printf("%d\n", ((uint)1 << 31)); continue; }
				R++; K--;
			}
			int ans = solve(L, R, K);
			printf("%d\n", flag * ((uint)1 << 31) + ans);
		}
	}
}


% 处理附件1(中文碎片) paper_reconstruction_2d('附件3'); % 处理附件2(英文碎片) paper_reconstruction_2d('附件4'); function paper_reconstruction_2d(folder_path) % 读取所有碎片图像 file_list = dir(fullfile(folder_path, '*.bmp')); num_files = length(file_list); % 检查碎片数量 if num_files ~= 209 error('错误:需要209个碎片(11×19),当前数量:%d', num_files); end % 文件名排序 file_names = {file_list.name}; num_indices = zeros(1, num_files); for i = 1:num_files [~, name, ~] = fileparts(file_names{i}); num_indices(i) = str2double(name); end [~, sorted_idx] = sort(num_indices); file_list = file_list(sorted_idx); % 预处理所有碎片 fragments = cell(1, num_files); fragment_ids = cell(1, num_files); text_ranges = zeros(num_files, 2); % 存储每张碎片的文字顶线和底线 for i = 1:num_files % 读取图像(兼容灰度/RGB) img = imread(fullfile(folder_path, file_list(i).name)); if size(img, 3) == 3 fragments{i} = rgb2gray(img); else fragments{i} = img; end fragment_ids{i} = file_list(i).name(1:end-4); % 检测文字行范围 [top, bottom] = detect_text_lines(fragments{i}); text_ranges(i,:) = [top, bottom]; end % 按文字行位置分组(11行) row_groups = group_by_text_lines(text_ranges); % 对每行碎片进行水平拼接 row_sequences = cell(11, 1); for row = 1:11 if length(row_groups{row}) ~= 19 error('行%d碎片数量不为19', row); end row_sequences{row} = sort_row_fragments(fragments, row_groups{row}); end % 按文字行位置排序行(从上到下) row_order = sort_rows_by_position(row_groups, text_ranges); % 生成最终序列和结果表格 [final_sequence, result_table] = generate_results(row_sequences, row_order, fragment_ids); disp('复原结果表格:'); disp(result_table); % 可视化拼接结果 visualize_reconstruction(fragments, row_sequences, row_order); end %% 核心函数:通过文字行位置分组 function row_groups = group_by_text_lines(text_ranges) % 计算每张碎片的文字行中心位置 centers = mean(text_ranges, 2); % 预分组(11行,按中心高度排序) [~, sorted_idx] = sort(centers); row_groups = cell(11, 1); for i = 1:11 row_groups{i} = sorted_idx((i-1)*19+1 : i*19); end % 验证分组正确性 for row = 1:11 row_ranges = text_ranges(row_groups{row}, :); avg_top = mean(row_ranges(:,1)); avg_bottom = mean(row_ranges(:,2)); % 检查行内文字范围是否一致 if any(abs(row_ranges(:,1) - avg_top) > 1) || ... any(abs(row_ranges(:,2) - avg_bottom) > 1) warning('行%d文字范围不一致,可能需要人工检查', row); end end end %% 核心函数:行间排序(按文字行垂直位置) function row_order = sort_rows_by_position(row_groups, text_ranges) % 计算每行的平均文字行位置 row_positions = zeros(11, 1); for row = 1:11 row_positions(row) = mean(mean(text_ranges(row_groups{row}, :))); end % 按垂直位置排序(从上到下) [~, row_order] = sort(row_positions); end %% 核心函数:生成结果表格 function [sequence, table] = generate_results(row_sequences, row_order, ids) sequence = []; table = cell(11, 19); for row = 1:11 row_idx = row_order(row); for col = 1:19 frag_idx = row_sequences{row_idx}(col); sequence = [sequence, frag_idx]; table{row,col} = ids{frag_idx}; end end end %% 可视化函数 function visualize_reconstruction(fragments, row_sequences, row_order) % 拼接所有行 full_img = []; for row = 1:11 row_img = []; for col = 1:19 row_img = [row_img, fragments{row_sequences{row_order(row)}(col)}]; end full_img = [full_img; row_img]; end % 显示结果 figure; imshow(full_img, []); title('基于文字行对齐的拼接结果'); imwrite(full_img, 'reconstructed_by_lines.bmp'); end %% 文字行检测函数 function [top_line, bottom_line] = detect_text_lines(img) bw_img = imbinarize(img); % bw_img = ~bw_img; horz_proj = sum(bw_img, 2); text_mask = horz_proj > 0.92*max(horz_proj); lines = find(text_mask); if isempty(lines) top_line = 1; bottom_line = size(img, 1); else top_line = min(lines); bottom_line = max(lines); end end %% 单行排序函数(保持不变) function sequence = sort_row_fragments(fragments, frag_indices) num_frags = length(frag_indices); left_edges = cell(1, num_frags); right_edges = cell(1, num_frags); for i = 1:num_frags img = fragments{frag_indices(i)}; left_edges{i} = img(:,1); right_edges{i} = img(:,end); end match_matrix = zeros(num_frags); for i = 1:num_frags for j = 1:num_frags if i == j match_matrix(i,j) = -Inf; else match_matrix(i,j) = -sum(abs(double(right_edges{i}) - double(left_edges{j}))); end end end [~, start] = max(cellfun(@mean, left_edges)); sequence = zeros(1, num_frags); sequence(1) = start; used = false(1, num_frags); used(start) = true; for pos = 2:num_frags [~, best] = max(match_matrix(sequence(pos-1), :)); if ~used(best) sequence(pos) = best; used(best) = true; else [sorted, sorted_idx] = sort(match_matrix(sequence(pos-1), :), 'descend'); for k = 1:num_frags if ~used(sorted_idx(k)) && isfinite(sorted(k)) sequence(pos) = sorted_idx(k); used(sorted_idx(k)) = true; break; end end end end sequence = frag_indices(sequence); end面对2013年全国大学生数学建模竞赛 B题碎纸复原模型与算法,请给出优化代码
最新发布
08-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值