链接:https://www.nowcoder.com/acm/contest/158/D
来源:牛客网
题目描述
将所有形如ax+1的数称为a-贝利福斯数,其中x是正整数。
一个a-贝利福斯数是a-贝利福斯素数,当且仅当它不能被分解成两个a-贝利福斯数的积。
现在给出a,n,问有多少个 ≤ n的a-贝利福斯数可以被分解成两个a-贝利福斯素数的积。
输入描述:
一行两个数a,n
输出描述:
一行一个数表示答案
示例1
输入
复制
4 25
输出
复制
1
先看一下欧拉筛素数的方法
const int N=1e5+10;//!!!修改 N
int prime[N];
bitset<N> vis;
void get_pri(){
int cnt = 0;
for(int i = 2; i <= N; i++){
if(!vis[i])prime[cnt++] = i;
for(int j = 0; j<cnt && 1LL*i*prime[j]<=1LL*N; j++){
vis[i*prime[j]]=1;//找到的素数的倍数不访问
if(i % prime[j] == 0) break;//关键!!!!
}
}
}
这道题,相同的思想,最后枚举两个素数看看他们的乘积是否出现过就好了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
const int maxn=2e7+10;
bitset<maxn*10> vis;
int cnt_pri,pri[maxn/2];
int num[maxn];
void init(int a,int n){
cnt_pri=0;int cnt_num=0;
for(int i=a+1;i<=n;i+=a)num[cnt_num++]=i;
for(int i=0;i<cnt_num;i++){
if(!vis[num[i]])pri[cnt_pri++]=num[i];
for(int j=0;j<cnt_pri&&1LL*pri[j]*num[i]<=n;j++){
vis[1LL*pri[j]*num[i]]=1;
if(num[i]%pri[j]==0)break;
}
}
}
int main(){
//freopen("123.txt","w",stdout);
//double t1=clock();
int a,n;
scanf("%d %d",&a,&n);
init(a,n);
//printf("%.2f\n",(clock()-t1)/CLOCKS_PER_SEC);
ll ans=0;
for(int i=0;i<cnt_pri;i++){
if(1LL*pri[i]*pri[i]>n)break;
for(int j=i;j<cnt_pri;j++){
ll sum=1LL*pri[i]*pri[j];
//printf("sum:%lld\n",sum);
if(sum>n)break;
if(vis[sum])ans++;//答案肯定是合数,我们肯定已经筛掉了,这样可以节省空间
vis[sum]=0;
}
}
printf("%lld\n",ans);
return 0;
}