2020牛客暑期多校第四场 D - Dividing Strings(思维/字符串模拟)

题目链接


这个题其实挺有意思的,因为一个显然的规律是如果差超过9必须舍弃,因为一位一位地拆开结果最多是 9 9 ,那么枚举长度的每个因数很容易想到,关键是第二个样例那种 10199 10199 ,前三位和后两位是最优的,通过推理不难发现存在这样的情况拆分的长度差只能为 1 1 ,且较大值一定为 100...00 ? 100...00? ,最小值一定是长度少一的 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;
}

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/107562915