Codeforces Beta Round #86 (Div. 2 Only) E Double Happiness 素数筛法,费马平方和定理

博客讨论了Codeforces编程竞赛中的一道题目,涉及数学和数论概念。内容涵盖如何找出在给定区间[l, r]内同时对Peter(奇素数)和Bob(能表示为两个数平方和的数)来说幸运的天数。通过运用费马平方和定理和优化的素数筛选算法来解决此问题。" 117943632,169065,SpringBoot项目在Gitee托管教程,"['Spring Boot', 'Gitee', 'Git', '代码托管']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

E. Double Happiness
time limit per test
3 seconds
memory limit per test
128 megabytes
input
standard input
output
standard output

On the math lesson a teacher asked each pupil to come up with his own lucky numbers. As a fan of number theory Peter chose prime numbers. Bob was more original. He said that number t is his lucky number, if it can be represented as:

t = a2 + b2, 
where  a, b are arbitrary positive integers.

Now, the boys decided to find out how many days of the interval [l, r] (l ≤ r) are suitable for pair programming. They decided that the day i(l ≤ i ≤ r) is suitable for pair programming if and only if the number i is lucky for Peter and lucky for Bob at the same time. Help the boys to find the number of such days.

Input

The first line of the input contains integer numbers l, r (1 ≤ l, r ≤ 3·108).

Output

In the only line print the number of days on the segment [l, r], which are lucky for Peter and Bob at the same time.

Examples
input
3 5
output
1
input
6 66
output
7

题目大意:求一个区间内满足,a^2+b^2=prime的(a,b)的数对。

题目思路:费马平方和定理,一个奇素数可以分解为两个数的平方和,那么这个奇素素一定是 4k+1 型的。(注意特判下2)

所以我们筛素数的同时对每个数判断一下。

然后我们要剪枝和优化,大概如下几点:

1:偶数全部都不满足,直接算而不用放进筛法里。

2:只用用奇素数进行素数筛,而且只晒出没有偶数因子的数。

3:筛法和判定一个数是否满足题目的条件同时进行。

4:bool[3e8]的内存是不够的,我们需要用bitset优化,bitset的空间,关于这个,我请教了一下q巨。


所以我们一般在windows64 下可以节省8倍空间

然后记得处理一下细节,即2这个素数不满足4k+1 型,但是它也是满足a^2+b^2的。

代码如下

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e8+10;
bitset<maxn>prime;
int Getprime(int l,int r)
{
	int cnt=0;
	if(l<=2&&2<=r) cnt++;
	l=max(l,3);
	if(l>r) return cnt;
	if(l%2==0&&r%2==0) cnt-=(r-l+2)>>1;//减去偶数不满足的情况 
	else if(l%2&&r%2) cnt-=(r-l)>>1;
	else if(l%2||r%2) cnt-=(r-l+1)>>1;
	cnt+=r-l+1;
	prime.reset();
	prime[0]=true;
	prime[1]=true;
	int i;
	for(i=3;i*i<=r;i+=2)
	{
		if(prime[i]) 
		{
			if(i>=l) cnt--;
			continue;
		}
		if(i>=l&&(i-1)%4) cnt--;
		for(int j=i*i;j<=r;j+=i<<1) prime[j]=true;
	}
	if(l%2==0) l++;
	i=max(l,i);
	for(;i<=r;i+=2)
	{
		if(prime[i]||(i-1)%4) cnt--;
	}
	return cnt;
}
int main()
{
	int l,r;
	while(~scanf("%d%d",&l,&r))
	{
		cout<<Getprime(l,r)<<endl;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值