Project-Euler problem 60 Prime pair sets

The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.

Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.


质数3, 7, 109, 和 673是值得注意的。将其中任意两个质数以任何顺序相连接产生的结果都是质数。例如,取7和109,连接而成的7109和1097都是质数。这四个质数的和是792,这也是满足这个性质的四个质数集合的最小总和。

找出满足这个性质的五个质数的集合中,集合数之和最小的。算出这个最小的和。


#include<iostream>
#include<stdio.h>
#include<set>
#include<map>
#include<algorithm>

using namespace std;

const int limit=100000001;
bool bprime[limit]= {0};
int prime[11010],nprime=0;
struct Edge
{
    int x,y;
    bool operator < (const Edge & b) const
    {
        return this->x < b.x;
    }
    Edge(int a=0,int b=0):x(a),y(b) {}
} data[40000];
int cnt=0;
int check(int a,int b,int c,int d,int e)
{
    int num[5]= {a,b,c,d,e};
    for(int i=0; i<5; i++)
        for(int j=0; j<5; j++)
        {
            if(i==j) continue;
            int tmp=num[i];
            int ans=num[j];
            while(tmp)
            {
                ans*=10;
                tmp/=10;
            }
            ans+=num[i];
            if (ans>=limit||bprime[ans]) return false;
        }
    return true;
}

bool bingo(int ary[],int n)
{
    int a=0;
    for(int b=a+1; b<n; b++)
        for(int c=b+1; c<n; c++)
            for(int d=c+1; d<n; d++)
                for(int e=d+1; e<n; e++)
                    if(check(ary[a],ary[b],ary[c],ary[d],ary[e]))
                    {
                        cout<<ary[a]<<" "<<ary[b]<<" "<<ary[c]<<" "<<ary[d]<<" "<<ary[e]<<endl;
                        cout<<ary[a]+ary[b]+ary[c]+ary[d]+ary[e]<<endl;
                        return true;
                    }
    return false;
}

bool ok(int a,int b)
{
    int tmp=a,n=b;
    while(n)
    {
        tmp*=10;
        n/=10;
    }
    tmp+=b;
    if(bprime[tmp]) return false;
    tmp=b,n=a;
    while(n)
    {
        tmp*=10;
        n/=10;
    }
    tmp+=a;
    return !bprime[tmp];
}

set<int> se;

int main()
{
    //freopen("out.txt","w",stdout);
    bprime[0]=bprime[1]=true;
    for(int i=2; i<10000; i++)
        if(!bprime[i])
            for(int j=i<<1; j<limit; j+=i)
                bprime[j]=true;
    for(int i=2; i<limit; i++)
        if(!bprime[i]&&i<10000)
            prime[nprime++]=i;
    int ans=0;
    for(int i=0; i<nprime; i++)
        for(int j=i+1; j<nprime; j++)
            if(ok(prime[i],prime[j]))
            {
                data[cnt++]=Edge(prime[i],prime[j]);
                data[cnt++]=Edge(prime[j],prime[i]);
            }
    sort(data,data+cnt); 
    int i=0;
    int ary[400],n;
    while(i<cnt)
    {
        se.clear();
        int x=data[i].x;
        se.insert(x);
        while(data[i].x==x)
            se.insert(data[i++].y);
        n=0;
        for(set<int>::const_iterator it=se.begin(); it!=se.end(); ++it)
            ary[n++]=*it;
        if(bingo(ary,n))
            return 0;
    }
    return 0;
}

/***
13 5197 5701 6733 8389
26033

about 9 seconds
***/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值