专栏文章

题解:P13159 [GCJ 2017 Qualification] Tidy Numbers

P13159题解参与者 1已保存评论 0

文章操作

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

当前评论
0 条
当前快照
1 份
快照标识符
@miod6z7t
此快照首次捕获于
2025/12/02 17:17
3 个月前
此快照最后确认于
2025/12/02 17:17
3 个月前
查看原文

P13159 Tidy Numbers - Solution

Problem Statement

给定一个数 NN,你要将它改为小于等于原数,且各位数字不递减的最大数。

Analysis

首先分情况讨论,若原数满足条件,则不必修改。否则,分析满足性质的数字。
设初次不符合规则的位置为 xx,即 Nx>Nx+1N_x>N_{x+1},先将 NxNx1N_x\gets N_x-1,也就是相当于退一位,这样才能满足小于原数。
再考虑后面的位数,由于已经满足 Nx1<NxN_x-1<N_x,因此后面的数字不会决定两数的大小关系,全部设为 99 一定是最优的
这样,就粗略地证明了贪心的正确性,可以实现。

Approach

使用字符串存储 NN,字符串为 SS。遍历找到 xxSxSx1S_x\gets S_x-1,再将后面的 Si9S_i\gets9,其中 i(x,n]i\in(x,n]。由于每次更新后可能仍然不合条件,所以要循环此操作,直到全串符合为止。
最后还要注意去掉前导零,使用 while(s[i]=='0') i++ 就可以实现。

Code

CPP
#include<bits/stdc++.h>
using namespace std;
string s;

void solve(){
	for(int i=1;i<s.size();i++){
        if(s[i-1]>s[i]){ //找x 
            s[i-1]--;
            for(int j=i;j<s.size();j++)
            	s[j]='9';
            solve();
        }
	}
}

void print(){
    int i=0;
    while(s[i]=='0') //去除前导零 
        i++;
    for(i;i<s.size();i++)
        cout<<s[i];
    cout<<endl;
}

int main(){
    int T;
    cin>>T;
    for(int t=1;t<=T;t++){
        cin>>s;
		solve(); 
        printf("Case #%d: ",t);
        print(); //输出答案,处理前导零 
    } 
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...