• 【POJ 2689】Prime Distance【数论,数学】


    题目大意:

    题目链接:http://poj.org/problem?id=2689
    llrr之间相邻的差最小以及最大的质数。


    思路:

    这道题真的是烦。。。
    这里写图片描述
    这里写图片描述
    MLE和RE了超级多次,最后发现是一个极其不起眼的东西。。。
    这道题l,r231l,r\leq 2^{31},但是rl106r-l\leq 10^6,所以可以考虑从l,rl,r方面入手。
    首先我们知道nn的质因子枚举到n\sqrt{n}就可以了,那我们可以先将不大于2312^{31}次方的质数用线性筛筛出来,时间复杂度O(r)O(\sqrt{r}),约为O(47000)O(47000)
    然后对于每一组数据,我们先从枚举每个质数,再从llrr枚举,每次直接加prime[i]prime[i],然后被枚举到的数就绝对是合数。这里的理论时间复杂度是O((rl)r)O((r-l)\sqrt{r}),语约为O(47000000000)O(47000000000),完全会TT。但是这只是理论,实际来说,当r=231r=2^{31}时,所有枚举的质数约为50005000个,第二重循坏最多执行500000500000次,最少执行11次,平均约为1010次!(经程序输出)
    那么这一段的时间复杂度就约为O(50000)O(50000),但是还是有一些卡时。
    当然你还可以用gotogoto再简化。在POJ上评测加了gotogoto会少20ms20ms(当然并不建议用gotogoto)。
    之后我们就求出了llrr之间的所有质数,那么接下来暴力枚举就可以啦!


    代码:

    #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;
    }
    
  • 相关阅读:
    vue2.0装jquery
    js new运算符
    Ajax请求Spring Mvc 时总是返回 302 Moved Temporarily
    工作笔记 --->新疆统计分析添加市场管理员相关功能笔记
    第十章:避免活跃性危险——Java并发编程实战
    第八章:线程池的使用——Java并发编程实战
    中介者模式——HeadFirst设计模式学习笔记
    解释器模式——HeadFirst设计模式学习笔记
    第七章:取消与关闭——Java并发编程实战
    蝇量模式——HeadFirst设计模式学习笔记
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998629.html
Copyright © 2020-2023  润新知