【POJ 2689】Prime Distance【數論,數學】
阿新 • • 發佈:2019-01-27
題目大意:
思路:
這道題真的是煩。。。
MLE和RE了超級多次,最後發現是一個極其不起眼的東西。。。
這道題,但是,所以可以考慮從方面入手。
首先我們知道的質因子列舉到就可以了,那我們可以先將不大於次方的質數用線性篩篩出來,時間複雜度,約為。
然後對於每一組資料,我們先從列舉每個質數,再從到列舉,每次直接加,然後被列舉到的數就絕對是合數。這裡的理論時間複雜度是,語約為 ,完全會。但是這只是理論,實際來說,當時,所有列舉的質數約為個,第二重循壞最多執行次,最少執行次,平均約為次!(經程式輸出)
那麼這一段的時間複雜度就約為,但是還是有一些卡時。
當然你還可以用再簡化。在POJ上評測加了會少(當然並不建議用)。
之後我們就求出了到之間的所有質數,那麼接下來暴力列舉就可以啦!
程式碼:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#define ll long long
#define M 1000020
#define Inf 1e16
using namespace std;
ll l,r,m,sum,minn,maxn,prime[M],v[M],tail,max_r,max_l,min_r,min_l;
bool ok,p[M];
void find_prime(ll n) //離線求質數(線性篩)
{
for (ll i=2;i<=n;i++)
{
if (!v[i])
{
prime[++m]=i;
v[i]=i;
}
for (ll j=1;j<=m;j++)
{
if (prime[j]>v[i]||i*prime[j]>n) break;
v[i*prime[j]]=prime[j];
}
}
}
int main()
{
find_prime(50000);
while (~scanf("%lld%lld",&l,&r))
{
sum=r-l+1;
memset(p,0,sizeof(p));
if (l==1) //特判,1不是質數
{
p[1]=1;
sum--;
}
for (ll i=1;prime[i]<=sqrt(r);i++)
for (ll j=l+(prime[i]-(l%prime[i]))%prime[i];j<=r;j+=prime[i]) //直接求出第一個質數,然後就每次加prime[i]
{
if (sum<2) goto stop; //不建議使用
if (j<0||prime[i]==j) continue;
if (!p[j-l+1]) sum--;
p[j-l+1]=true;
}
stop:
if (sum<2)
{
printf("There are no adjacent primes.\n");
continue;
}
minn=Inf;
maxn=-Inf;
tail=-1;
for (ll i=l;i<=r;i++) //爆枚
if (!p[i-l+1])
{
if (tail>-1)
{
if (i-tail>maxn)
{
maxn=i-tail;
max_l=tail;
max_r=i;
}
if (i-tail<minn)
{
minn=i-tail;
min_l=tail;
min_r=i;
}
}
tail=i;
}
printf("%lld,",min_l);
printf("%lld are closest, ",min_r);
printf("%lld,",max_l);
printf("%lld are most distant.\n",max_r);
}
return 0;
}