这道题和幸运数字差不多,也是一个深搜就解决了。
每个能放加号的位置都有两种状态: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。