26黑龙江省赛B补题
B.最大数码2
在此感谢xiaowang524 ,看了他的代码才略懂这题
题意
1.令f(x)=x中最大的数
2.找到区间l,r中f(x)最大切字典序最小的x
其中字典序出现了新的介绍:称长度为x的字符串P =p1,p2···px 的字典序小于长度为y 的字符串Q=q1,q2···qy,若
·x<y且对于所有1≤i≤x有pi=qi,
或者
·存在一个整数1≤t≤min(x,y),对于所有1≤i<t有pi=qi,且 pt<qt。
思考
- 最容易想到的就是当l,r区间未超过10很容易用枚举的方法进行就行了
那么怎么处理区间>=10的呢? - 很容易想到对于r-l>9,f(x)=9。
接下来就是怎么求x了。 - 想到只有f(x)=9才会满足要求。那么我们只要分析(下文中的l,r都转换成字符串)l,r的长度区间就行,因为如果l.size()=2,那么肯定咱们要选的长度为2的x是待定答案,但是我们要想如果咱们找到的值比l低明显不符合。所以我们就要确定范围。这些文尾再写吧。
上代码
代码展示
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<ll,ll>;
const int mod=998244353;
ll pw10[11];
ll f(ll num)
{
char ch='0';
string s=to_string(num);
for(auto si:s)
{
if(si>ch)ch=si;
}
return ch-'0';
}
bool cmp(ll x,ll y)
{
string X=to_string(x),Y=to_string(y);
for(ll i=0;i<min(X.size(),Y.size());i++)
{
if(X[i]!=Y[i])return X[i]<Y[i];//1<9 return 1
}
return 1;
}
void solve()
{
ll l,r;
cin>>l>>r;
string L=to_string(l),R=to_string(r);
ll ans=l;
// string s1=to_string(r);
ll mx=0;
for(ll i=L.size();i<=R.size();i++)
{
ll lb=max(l,pw10[i-1]),rb=min(r,pw10[i]-1);
for(ll x=lb;x<=min(rb,lb+9);x++)
{
ll tmx=f(x);
// string s2=to_string(x);
if((tmx>mx)||(tmx==mx&&cmp(x,ans)))mx=tmx,ans=x;
}
}
cout<<mx<<' '<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
pw10[0]=1;
for(ll i=1;i<=10;i++)pw10[i]=pw10[i-1]*10;
ll T=1;
cin>>T;
while(T--)solve();
return 0;
}
/*
心中无女人
比赛自然神
模板第一页
忘记心上人
*/
ok,继续介绍咱们怎么思考
对于确定范围首先一定要满足r.size()>=len>=l.size()这样我们不会做无效的枚举,然后确定里面的的范围即x的范围,慢慢来
先说x的下界当x刚开始的时候就要看l和pw10[i-1](pw10是表示在长度i位时的最小数,比如三位数100就是最小数,10的i次方)。
选择最大值,以为如果pw10[i-1]跟l比时是最优的话,小于l是不符合舍去,
如果大于l的话明显l就不是最优,因为如果l=9,那么pw10[i-1]=10,但是区间是>=10的必然会有19比9最优。
x的上届就是r和pw10[i]里取最小值了大了不满足,小了当然最优,然后我们只需要进行遍历本身和下界+9取最小就行,下界+9,是自身加上在内的十个数内肯定很会有一个是f(x)=9
浙公网安备 33010602011771号