刚开始做的时候认为暴力会超时,所以没做,但仔细想想,最高为15位,两边最高为14位,但只需枚举2^(14-1),即2^13(8192) 即可。
具体是怎么枚举的呢。。。
比如1212这个数据
等号可以放在三个位置,所以先枚举等号的位置
然后,再枚举两边的数字能够组成的数字和,比如1=212,左边的数字的组合情况只有是1,而右边的可以是2+1+2=5,可以是21+2=23,可以使2+12=14,还可以使212
所以怎样划分这些数字就是关键,那么我们可以想象一下,对于2+1+2 这个分割方法,我们用二进制的表示方法010或101表示,那么2+12就可以表示成100或011。212表示成000或111即相邻的几个数字要表示成一个数字的话,他们所对应的下标成相同,所以用二进制的思想就可以把这些数字分组。
具体是怎么枚举的呢。。。
比如1212这个数据
等号可以放在三个位置,所以先枚举等号的位置
然后,再枚举两边的数字能够组成的数字和,比如1=212,左边的数字的组合情况只有是1,而右边的可以是2+1+2=5,可以是21+2=23,可以使2+12=14,还可以使212
所以怎样划分这些数字就是关键,那么我们可以想象一下,对于2+1+2 这个分割方法,我们用二进制的表示方法010或101表示,那么2+12就可以表示成100或011。212表示成000或111即相邻的几个数字要表示成一个数字的话,他们所对应的下标成相同,所以用二进制的思想就可以把这些数字分组。
再来看,对于100和011的分组情况其实是一样的,都是第一个数为一组,后两个数是一组,所以只需要枚举一次就行,所以规模就小了一般。
#include"iostream"
#include"map"
#include"stdio.h"
#include"string.h"
using namespace std;
map< __int64,int> m1,m2;
map< __int64,int>::iterator it,_it;
char str[20];
int len;
void solve(char *s,int x,map<__int64,int> &ma)
{
__int64 sum,t;
int k=1<<(x-1);
for(int i=0;i<k;i++)
{
int w=0;
sum=0;t=0;
for(int j=0;j<x;j++)
{
if(!(w^(1&(i>>(x-j-1)))))//这步最为关键,要理解,判断和上一个字符是否来自一组
{
t=t*10+s[j]-'0';
}
else
{
sum+=t;
t=s[j]-'0';
if(w)
w=0;
else
w=1;
}
}
sum+=t;
it=ma.find(sum);
if(it==ma.end())
ma[sum]=1;
else
it->second++;
}
}
int main()
{
int n;
while(gets(str)!=NULL)
{
if(!strcmp("END",str))
break;
n=0;
len=strlen(str);
for(int i=0;i<len-1;i++)
{
m1.clear();m2.clear();
solve(str,i+1,m1);
solve(str+i+1,len-i-1,m2);
for(it=m1.begin();it!=m1.end();++it)
{
_it=m2.find(it->first);
if(_it!=m2.end())
n+=it->second*_it->second;
}
}
printf("%d\n",n);
}
return 0;
}