社区讨论

0分,求,悬棺

P1323删数问题参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mjxo44na
此快照首次捕获于
2026/01/03 10:12
2 个月前
此快照最后确认于
2026/01/06 14:35
2 个月前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 3 * 1e4 + 5;
int k , m;
int a[N];//第i位数字 
bool eat[N];//是否被删除 
string num;//存数字 
void into(){//预处理 
	a[1] = 1;
	int xx = 1 , yy = 1;
	int toooot = 3 * 1e4;
	for(int i = 2;i <= toooot;i ++){
		if(a[xx] * 2 + 1 < a[yy] * 4 + 5){
			a[i] = a[xx ++] * 2 + 1;
		}else{
			a[i] = a[yy ++] * 4 + 5;
		}
	}
}//其中flag表示是否进行了删除行为 , 返回值表示是否还能再删除
char get_next(int now){//获得未被删除的下一位数的位置 
	int len = num.length();
	while(1){
		now ++;
		if(eat[now] == 0){
			return now;
		}else if(now == len){
			return len;
			break;
		}
	}
} 
bool to_eat(bool &flag){//进行一轮删除 
	int len = num.length();
	flag = 0;
	for(int i = 0;i < len;i ++){
		if(eat[i]){
			continue;
		}if(m == 0){
			return 1;
		}
		if(num[i] < num[get_next(i)]){
			eat[i] = 1;
			flag = 1;
			m --;
		}
	} 
	if(m == 0){
		return 1;
	} 
	return 0;
}
void to_end(){//最后从后往前删除 
	int i = num.length();
	while(m){
		i --;
		if(eat[i] == 0){
			eat[i] = 1;
			m --;
		}else{
			continue;
		}
	}
}
signed main(){
	cin >> k >> m;
	into();
	for(int i = 1;i <= k;i ++){
//		cout << a[i];
		num += to_string(a[i]);
	}
	cout << num;
	while(1){
		bool flag;
		if(to_eat(flag) == 1 || flag == 0){//删除完毕或者无法继续删除 
			break;
		}
	}
	cout << endl;
	to_end();
	int len = num.length();
	for(int i = 0;i < len;i ++){
		if(eat[i] == 0){
			cout << num[i];
		}
	}
	return 0;
}
大概思路:
先预处理所有数,然后从前往后开始,只要该数比后面一位小就删除(在代码中通过 eat[i] 来表示是否被删除)get_next(int now) 表示第 ii 位后第一个没被删除的位置。bool to_eat(bool &flag) 进行一次删除操作,其中 flag 为本次是否删除了数,返回值表示是否删够了数。如果删够了或者没有进行删除操作则从后面开始删除剩余的 mm 个数(to_end() 实现)。

回复

0 条回复,欢迎继续交流。

正在加载回复...