代码改变世界

srm334 div1

2012-05-02 14:26  macaroniz  阅读(147)  评论(0)    收藏  举报

250pt

思路很明显,枚举所有的合法序列然后代入检验。

可以降低复杂度的地方在于如何快速求和,我的方法是直接预处理出来求和之后每个字母的系数是多少就可以了。

时间复杂度是O(10!*10)

class EncodedSum
{
public:
    long long ai[15];
    long long apow[15];
    long long maximumSum(vector <string> numbers)
    {
        apow[0] = 1;
        for(int i = 1;i < 15;i++) apow[i] = apow[i-1] * 10;
        memset(ai,0,sizeof ai);
        for(int i = 0;i < numbers.size();i++)
            for(int j = 0;j < numbers[i].length();j++)
                ai[numbers[i][j] - 'A'] += apow[numbers[i].length() - 1 - j];
        int arr[10] = {0,1,2,3,4,5,6,7,8,9};
        long long ans = 0;
        do
        {
            bool flag = true;
            for(int i = 0;i < numbers.size();i++)
                if(arr[numbers[i][0]-'A'] == 0) flag = false;
            if(flag)
            {
                long long t1 = 0;
                for(int i = 0;i < 10;i++)
                    t1 += ai[i] * arr[i];
                if(ans < t1) ans = t1;
            }
        }while(next_permutation(arr,arr+10));
        return ans;
    }
};

 

500pt

在观察到7*9^6依然是个7位数之后,方法就很明显了,按照题意描述进行记忆化搜索。

但是这里有个不好处理的地方,就是结尾一定会形成一个环(a1->a2...->an->b1->b2...->bm->b1),如何将b1->b2.....->bm这个环破开让我想了好久,最还还是看了别人的代码才明白的。

实际上只需要记录一下每个数字被访问了几次,如果被访问了一次以上,那么直接return当前保存的最优值即可。

否则就再环里再跑一遍,这样更新就肯定不会有错。

详细的可以看代码,比较好理解。

long long dp[4000000];
long long vis[4000000];
int apow[11];
class ExtendedHappyNumbers
{
public:
    int K;
    long long minx(long long a,long long b)
    {
        return a < b ? a : b;
    }

    long long calc(long long num)
    {
        if(vis[num] > 1) return dp[num];
        vis[num]++;
        long long next = 0,_num = num;
        while(_num != 0)
        {
            next += apow[_num % 10];
            _num /= 10;
        }
        dp[num] = num;
        dp[num] = minx(num,calc(next));
        return dp[num];
    }

    long long calcTheSum(int A, int B, int _K)
    {
        K = _K;
        long long ans = 0;
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));
        memset(apow,0,sizeof(apow));
        for(int i = 1;i < 10;i++)
        {
            apow[i] = 1;
            for(int j = 1;j <= K;j++) apow[i] *=i;
        }
        for(int i = A;i <= B;i++)
            ans += calc(i);
        return ans;
    }
};

1000pt(留着做)