2023首届大学生算法大赛 - 帮助小强

 


这道题和幸运数字差不多,也是一个深搜就解决了。

每个能放加号的位置都有两种状态:1、放加号    2、不放加号

N<=10^15,故能放加号的位置最多14个,复杂度为2^14=16384。

易得解空间树,根据树写出递归代码。

AC代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n,ans,nl,t;
bool flag[20];
int get(int l,int r){
    int res=n/pow(10,nl-r);
    int k= pow(10,r-l+1);
    return res%k;
}
void dfs(int i){
    if(i==nl+1){
        int pos=1,res=0;
        flag[nl]=true;
        for(int j=1;j<=nl;++j)
            if(flag[j]){
                res+= get(pos,j);
                pos=j+1;
            }
        ans+=res;
        return;
    }

    flag[i+1]=true;
    dfs(i+1);
    flag[i+1]=false;
    dfs(i+1);
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    cin>>n;
    t=n;
    while(t){
        nl++;
        t/=10;
    }

    dfs(0);
    cout<<ans/4;
    return 0;
}

代码中有几处关键的地方。

1、get函数,假如有数字5892,那么get(1,3)=589,get(2,3)=89。根据下标拿出部分,方便累加。

2、以打标记的方法实现加号插空,如果flag[1]=true,那么[1,1]要变成子部分累加。因为加过了,所以下一个pos从2开始,即i+1。如果下一个flag[4]=true,就能累计[2,4]子部分。

3、因为采用的是尾部判定实现加上子部分,不难发现如果循环到最后一位不是true,那就不会加上,所以开头要flag[nl]=true。

4、由于深搜代码复杂度很低,所以没有优化,导致每种情况都会加上4次,所以输出要除以4。

猜你喜欢

转载自blog.csdn.net/qq_17807067/article/details/129940690