HDU 3823 Prime Friend

Prime Friend

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3325    Accepted Submission(s): 673


Problem Description
Besides the ordinary Boy Friend and Girl Friend, here we define a more academic kind of friend: Prime Friend. We call a nonnegative integer A is the integer B’s Prime Friend when the sum of A and B is a prime.
So an integer has many prime friends, for example, 1 has infinite prime friends: 1, 2, 4, 6, 10 and so on. This problem is very simple, given two integers A and B, find the minimum common prime friend which will make them not only become primes but also prime neighbor. We say C and D is prime neighbor only when both of them are primes and integer(s) between them is/are not.
 

Input
The first line contains a single integer T, indicating the number of test cases.
Each test case only contains two integers A and B.

Technical Specification

1. 1 <= T <= 1000
2. 1 <= A, B <= 150
 

Output
For each test case, output the case number first, then the minimum common prime friend of A and B, if not such number exists, output -1.
 

Sample Input
  
2 2 4 3 6
 

Sample Output
  
Case 1: 1 Case 2: -1
 

Author
iSea@WHU
 

Source

题意:给两个数m,n,求使m,n加上一个数后变成两个相邻数素数的最小数
时间限制是2S,可以直接暴力求解,问题是素数打表范围该怎么考虑,因为m,n<=150,打表范围应该到任意m-n(m-n为偶数,1除外)都能找到对应的两个素数差值等于m-n
可以暴力打表先找一找规律

void prime()
{
    p[0]=0;
    mem(vis,0);
    mem(num,0);
    for(int i=2;i<=Max;i++)
    {
        if(!vis[i])p[++p[0]]=i;
        for(int j=1;j<=p[0]&&(ll)i*p[j]<=Max;j++)
        {
            vis[i*p[j]]=1;
            if(!(i%p[j]))break;
        }
    }
    for(int i=1;i<p[0];i++)
    {
        int o=p[i+1]-p[i];
        num[o]++;
    }
    for(int i=0;i<=150;i++)
	pf("%d ",num[i]);
}
若打表到1e7,在后面的只里面仍然有几个连续为0(无法满足条件),打表范围到2e7时,偶数位(加上1)全部不为0,这时就满足条件了
暴力的方式有两种,一种是直接枚举所有相邻素数,求出最小的那个即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<cmath>
#include<vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pi acos(-1.0)
#define eps 1e-10
#define pf printf
#define sf scanf
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define e tree[rt]
#define _s second
#define _f first
#define all(x) (x).begin,(x).end
#define mem(i,a) memset(i,a,sizeof i)
#define for0(i,a) for(int (i)=0;(i)<(a);(i)++)
#define for1(i,a) for(int (i)=1;(i)<=(a);(i)++)
#define mi ((l+r)>>1)
#define sqr(x) ((x)*(x))

const int inf=0x3f3f3f3f;
const int Max=2e7+1;
int t,m,n,p[Max/10];
bool vis[Max+1];

void prime()
{
    p[0]=0;
    mem(vis,0);
    for(int i=2;i<=Max;i++)
    {
        if(!vis[i])p[++p[0]]=i;
        for(int j=1;j<=p[0]&&(ll)i*p[j]<=Max;j++)
        {
            vis[i*p[j]]=1;
            if(!(i%p[j]))break;
        }
    }
}

int main()
{
    prime();
    sf("%d",&t);
    for1(i,t)
    {
        sf("%d%d",&m,&n);
        pf("Case %d: ",i);
        if(m>n)swap(m,n);
        int ans=-1;
        for(int i=2;i<=p[0];i++)
            if(p[i]-n>=0&&p[i-1]-m>=0)
                if(p[i]-n==p[i-1]-m)
                {
                    ans=p[i]-n;
                    break;
                }
        pf("%d\n",ans);
    }
    return 0;
}

时间为1300MS比较慢

因为1-150最大差值才149,在素数打表后预处理一下就行,再枚举的话会快很多

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<cmath>
#include<vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pi acos(-1.0)
#define eps 1e-10
#define pf printf
#define sf scanf
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define e tree[rt]
#define _s second
#define _f first
#define all(x) (x).begin,(x).end
#define mem(i,a) memset(i,a,sizeof i)
#define for0(i,a) for(int (i)=0;(i)<(a);(i)++)
#define for1(i,a) for(int (i)=1;(i)<=(a);(i)++)
#define mi ((l+r)>>1)
#define sqr(x) ((x)*(x))

const int inf=0x3f3f3f3f;
const int Max=2e7+1;
bool vis[Max+1];
int p[Max/10],num[200],pos[200][200],t,m,n;

void prime()
{
    p[0]=0;
    mem(vis,0);
    mem(num,0);
    for(int i=2;i<=Max;i++)
    {
        if(!vis[i])p[++p[0]]=i;
        for(int j=1;j<=p[0]&&(ll)i*p[j]<=Max;j++)
        {
            vis[i*p[j]]=1;
            if(!(i%p[j]))break;
        }
    }
    for(int i=1;i<p[0];i++)
    {
        int o=p[i+1]-p[i];
        if(o<=150&&num[o]<200)//不需要计算出那么多的素数,一个差值对应200个已经足够了
            pos[o][num[o]++]=p[i];
    }
}

int main()
{
    prime();
    sf("%d",&t);
    for1(i,t)
    {
        sf("%d%d",&m,&n);
        if(m>n)swap(m,n);
        int k=n-m;
        int ans=-1;
        for(int i=0;i<num[k];i++)
            if(pos[k][i]>=m)
            {
                ans=pos[k][i]-m;
                break;
            }
        pf("Case %d: %d\n",i,ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值