Project Euler 51 Prime digit replaccements(列挙)

3490 ワード

スーパートランスポート:http://projecteuler.net/problem=51
 
この問題は暴力列挙です.O 3最適化後2秒以上です.
まず、素数を列挙して、代わりの位置を列挙します.dcを現在の列挙から素数までの桁数に設定します. (1< 
コードは以下の通りです
 
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

int p[100010];
int pIndex = 0;

inline int isPrime(int x)
{
    if (x <= 1)
        return 0;
    int m = (int)sqrt(x);
    for (int i = 2; i <= m; i++)
    {
        if (!(x % i))
            return 0;
    }
    return 1;
}

inline void genPrimeTable(int upBound)
{
    for (int i = 2; i <= upBound; i++)
    {
        if (isPrime(i))
            p[pIndex++] = i;
    }
}

inline int calcDigitsCount(int x)
{
    int ans = 0;
    while (x)
    {
        ans++;
        x /= 10;
    }
    return ans;
}

inline int replaceDigit(int x, int pos, int newVal)
{
    char buffer[15];
    sprintf(buffer, "%d", x);
    buffer[pos - 1] = newVal + '0';
    sscanf(buffer, "%d", &x);
    return x;
}

inline int calcMaxPrimeFamilyMemberCount(int x)
{
    int dc = calcDigitsCount(x);
    int retVal = 0;

    for (int i = 1; i < (1 << dc); i++)
    {
        int ans = 0;

        char bufferX[15];
        sprintf(bufferX, "%d", x);
        int preTestI = i;
        int hash[10];
        memset(hash, 0, sizeof(hash));

        for (int k = 1; k <= dc; k++)
        {
            int flag = preTestI & 0x1;
            preTestI >>= 1;

            if (flag)
                hash[bufferX[k - 1] - '0'] = 1;
        }

        int sum = 0;
        for (int k = 0; k <= 9; k++)
            sum += hash[k];
        if (sum != 1)
            continue;

        for (int newVal = 9; newVal >= 0; newVal--)
        {
            if ((i & 0x1) && !newVal)
                continue;

            int tmpRes = i;
            int tmpX = x;

            for (int j = 1; j <= dc; j++)
            {
                int flag = tmpRes & 0x1;
                tmpRes >>= 1;

                if (flag)
                    tmpX = replaceDigit(tmpX, j, newVal);

            }
            if (isPrime(tmpX))
                ans++;
        }

        retVal = retVal > ans ? retVal : ans;
    }

    return retVal;
}

int main()
{
    genPrimeTable(200000);

    int ans = 0;

    for (int i = 0; i < pIndex; i++)
    {
        int res = calcMaxPrimeFamilyMemberCount(p[i]);

        if (res == 8)
        {
            ans = p[i];
            break;
        }
    }
    printf("%d
", ans); return 0; }