题目链接
这个题其实挺有意思的,因为一个显然的规律是如果差超过9必须舍弃,因为一位一位地拆开结果最多是 9 9 9,那么枚举长度的每个因数很容易想到,关键是第二个样例那种 10199 10199 10199,前三位和后两位是最优的,通过推理不难发现存在这样的情况拆分的长度差只能为 1 1 1,且较大值一定为 100...00 ? 100...00? 100...00?,最小值一定是长度少一的 99...999 ? 99...999? 99...999?,那么就按这样的思路去枚举即可
我自己写的代码又臭又长,debug半天找不到毛病,然后去网上看题解,发现相比于截取字符串,用指针大大减少了操作难度和时间复杂度,然后就学习了一手,指针在这里还是香
Reference:https://blog.csdn.net/bbbll123/article/details/107497838
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
char s[maxn];
int a[maxn],b[maxn],sum[maxn];
int n;
bool cmp(int *a,int *b,int x){ //判断a[]和b[]的大小
for(int i=0;i<x;i++) if(a[i]!=b[i]) return a[i]<b[i];
return 0;
}
void Minus(int *a,int *b,int x){
for(int i=x-1;i>=0;i--) a[i]-=b[i]; //因为a[]一定是比b[]大的,那么可以贪心相减然后处理进位
for(int i=x-1;i>=0;i--) if(a[i]<0){
a[i-1]--;
a[i]+=10;
}
}
int solve(int x){ //解决长度相同的函数
int *mi=a+1,*mx=a+1; //因为长度相同,所以使用指针维护即可
for(int i=1;i<=n;i+=x){
if(x>1 && !a[i]) return 9; //出现前缀0直接返回
if(cmp(a+i,mi,x)) mi=a+i;
if(cmp(mx,a+i,x)) mx=a+i;
}
memcpy(b,mx,sizeof(int)*(x+10));
Minus(b,mi,x);
for(int i=0;i<x-1;i++) if(b[i]) return 9; //相减之后只有前x-1位必须为0
return b[x-1];
}
int cal(int x){ //解决长度不同的函数
int p=1,fn=9,fz=0;
while(p<=n){
if(a[p]==1){
if(p+x>n || sum[p+x-1]-sum[p]) return 9;
fz=max(fz,a[p+x]);
p+=x+1;
}else{
if(p+x-1>n || sum[p+x-2]-sum[p-1]!=9*(x-1)) return 9;
fn=min(fn,a[p+x-1]);
p+=x;
}
}
return 10+fz-fn;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
scanf("%d",&t);
while(t--){
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++) a[i]=s[i]-'0',sum[i]=sum[i-1]+a[i];
int ans=9;
for(int i=1;i<=n/2;i++){
ans=min(ans,cal(i));
if(n%i==0){
ans=min(ans,solve(i));
}
}
printf("%d\n",ans);
}
return 0;
}