Dividing Strings
4
2
08
5
10199
7
9710296
8
12341234
8
2
6
0
给定长度为n的数字,你可以将其分割成几个更小的数字。求对于任意一种分割方式, m a x − m i n max-min max−min的最小值是多少。
深解题意:例如给定12341234,你可以分成123|412|34,此时 m a x − m i n max-min max−min=412-34,显然不是最小。而真正的最小是分成1234|1234,此时 m a x − m i n max-min max−min=1234-1234=0,最小。
稍一分析,可知答案必然小于10。因为不管怎样,总是可以将其每个数字都分开,此时答案最大是9-0=9,因此任何解一旦超过9,就一定不如每个数字全部分开,即非最优。
由此可以推得,最大值和最小值要么都是同样的位数,要么就是1000…x,9999…y的样子,这样才能保证它们的差不比沙雕解法差。
推理后即可得出正解,分两种情况:
此时,位数必定是n的因子,因此只要枚举n的因子,然后算一遍答案,与历史最优取优即可。
此时,其形式是固定的,对于每个长度,都去找一遍这个最后一位的x,y即可。
高精,下标,指针。容易成为做题时的WAWA点。
#include
#define ll long long
#define inf 1<<30
using namespace std;
void sub(int* a,int* b,int len){
for(int i=1;i<=len;i++) a[i]-=b[i];
for(int i=len;i>=1;i--) if(a[i]<0) a[i]+=10,a[i-1]--;
}//同位高精减法
bool cmp(int* a,int* b,int len){for(int i=1;i<=len;i++) if(a[i]!=b[i]) return a[i]<b[i];return 0;}
//比较大小,小返回1
const int MAXN=1e5+10;
char s[MAXN];
int a[MAXN],pre[MAXN],b[MAXN];//pre前缀和,用于快速判断差1时的两种形式
int sol_xd(int p,int len){//第一种情况
if(p>1&&!a[1]) return 9;//前导0存在的话就直接不行了,位数不一样了
int *mx=a,*mn=a;//啊指针,有大佬不用指针的改法吗,(用for的话也还是算了)发下。
for(int i=0;i<len;i+=p){
if(p>1&&!a[i+1]) return 9;//前导0
if(cmp(a+i,mn,p)) mn=a+i;
if(cmp(mx,a+i,p)) mx=a+i;//打擂台求最值
}
memcpy(b,mx,sizeof(int)*(p+10));//+10防止减成负数,cpy一份是因为指针会导致原来的数组也改变
sub(b,mn,p);//减
for(int i=1;i<p;i++) if(b[i]) return 9;//如果减出来不是一位数,那么也是不对的
return b[p];
}
int sol_cha1(int p,int len){//第二种情况
int pos=1,z_last=0,n_last=9;
while(pos<=len){
if(a[pos]==1){
if(pos+p>len||pre[pos+p-1]-pre[pos]>0) return 9;//快速判断是否全0
z_last=max(z_last,a[pos+p]);pos+=p+1;
}
else{
if(pos+p-1>len||pre[pos+p-2]-pre[pos-1]!=p*9-9) return 9;//快速判断是否全9
n_last=min(n_last,a[pos+p-1]);pos+=p;
}//这里的最大和最小要想清楚
}return 10-n_last+z_last;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
int ans=9;
scanf("%d",&n);scanf("%s",s+1);
for(int i=1;i<=n;i++) a[i]=s[i]-'0';
for(int i=1;i<=n;i++) pre[i]=pre[i-1]+a[i];//求前缀和
for(int i=1;i<=n/2;i++){
ans=min(ans,sol_cha1(i,n));//第二种每个长度都求
if(n%i==0) ans=min(ans,sol_xd(i,n));//第一种是因子才求
}
printf("%d\n",ans);
}
}
好难一题,讨厌的全上了,高精+指针,woc。
感谢。