HDU-4403 A very hard Aoshu problem 枚举

直接枚举等号所在位置,然后左右两边用两个MAP来记录组成和的个数,然后运用乘法原理得到答案。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
#include<string>
#define LL long long
using namespace std;

char s[20];

int len;

map<long long,int>fmp, tmp;

long long get(int x, int y) {
    long long ret = 0;
    for (int i = x; i <= y; ++i) {
        ret = ret * 10 + s[i] - '0';
    }    
    return ret;
}

void cal(int a, int b, map<long long,int>&mp) {
    if (a == b) {
        ++mp[s[a]-'0'];
        return;
    }
    int mask = 1 << (b-a), last;
    for (int i = 0; i < mask; ++i) {
        long long temp = 0;
        last = a;
        for (int j = 0; j < (b-a); ++j) {
            if (i & (1 << j)) {
                temp += get(last, a + j);
                last = a + j + 1;
            }
        }
        temp += get(last, b);
        ++mp[temp];
    }
}

long long solve(int x) {
    long long ret = 0;
    fmp.clear(), tmp.clear();
    map<long long, int>::iterator it;
    cal(0, x, fmp);
    cal(x+1, len-1, tmp);
    for (it = fmp.begin(); it != fmp.end(); ++it) {
        ret += (long long)(it->second) * (long long)tmp[it->first];
    }
    return ret;
}

int main(  )
{
    long long ret;
    while (scanf("%s", s), s[0] != 'E') {
        ret = 0;
        len = strlen(s);
        for (int i = 0; i <= len-2; ++i) {
            // 枚举等号所在的位置
            ret += solve(i);
        }
        printf("%I64d\n", ret);
    }
    return 0;
}

 

posted @ 2012-09-22 21:07  沐阳  阅读(356)  评论(0编辑  收藏  举报