记 \(f(x)\) 为最小的大于 \(x\) 的 \(y\),使得 \(x\) 是 \(y\) 的子串。易得:
\[f(x)=\min(10x,x+10^{|x|})
\]
其中 \(|x|\) 表示 \(x\) 的位数。
可以发现,\(f(x)\) 为一个严格单调递增的函数。
考虑贪心策略,显然选小的数不如选大的数优,因为小的数更有可能成为别的数的子串。于是,我们要求的其实就是这样一个集合 \(\mathbb{A}\),满足:
\[\mathbb{A}=\{x\in[l,r]\mid f(x)>r\}
\]
因为 \(f(x)\) 是严格单增的,因此二分即可。
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define read(x){\char ch;\int fu=1;\while(!isdigit(ch=getchar()))\fu-=(ch=='-')<<1;\x=ch&15;\while(isdigit(ch=getchar()))\x=(x<<1)+(x<<3)+(ch&15);\x*=fu;\
}
#define int ll
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int pw10[]={
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000};
il int len(int x){int res=0;do{res++,x/=10;}while(x);return res;
}
il int f(int x){return min(x*10,x+pw10[len(x)]);
}
namespace cplx{bool end;il double usdmem(){return (&begin-&end)/1048576.0;}
}
signed main(){
// for(int i=1;i<=33;i++){
// cout<<i<<" "<<f(i)<<"\n";
// }int T;read(T);while(T--){int l,r,L,R;read(l)read(r);L=l,R=r;while(l<r){int mid=(l+r)>>1;if(f(mid)>R){r=mid;}else{l=mid+1;}}printf("%d\n",R-l+1);}return 0;
}
}
signed main(){return asbt::main();}