题目目录:
No.1 B2137 判决素数个数
No.2 B2138 最大质因子序列
No.3 B2140 二进制分类
OK,开始正文!
第一题: B2137 判决素数个数
题目描述
求 X,Y 之间的素数个数(包括 X 和 Y)。
输入格式
两个整数 X 和 Y(1≤X,Y≤1.1×10^6)。
输出格式
输出一个整数,表示 X,Y 之间的素数个数(包括 X 和 Y)。
输入输出样例
输入 #1
1 100
输出 #1
25
思路:
首先,我们需要知道:质数是什么
质数,又称素数,如果一个数除了1和它本身外没有其他因数,那么它就是质数(温馨提示:1不是质数!不然,你分解质因数,随便写几个1都行,就乱套了,而且质数都是2个因数,1只有1个,所以不算)
所以,在循环里面先设一个f=1(假设是质数)只要从2遍历到n-1,如果能整除就f=0(不是质数)
最后如果f=1的话就是质数,计数器++
此外,题目并没有说x大还是y大,所以还得比较一下,如果顺序错误就调换一下顺序,再注意一下对1的判断
既然如此,我们很快就可以写出一份代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int x,y;
cin >> x >> y;
int cnt=0;
if(x>y)
{
int t=x;
x=y;
y=t;
}
for(int i=x;i<=y;i++)
{
int f=1;
for(int j=2;j<i;j++)
{
if(i%j==0)
{
f=0;
}
}
cnt+=f&&i!=1;
}
cout<<cnt;
return 0;
}
这份代码是不是OK了呢?当你提交这份代码,你将会得到:
这是为什么呢?
这份程序套了两层循环,其中,第一层循环最多可能执行1100000次,而第二层循环最多也是执行1100000次,时间复杂度达到了平方级别,这.....肯定超时呀!
那么,我们就要换一种方法思考:
假设有一个数n,如果它的一个因子在[1,sqrt(n)]范围内,那么和这个因子相对的另一个因子一定在[sqrt(n),n]范围内,这是为什么呢?
设两个因子分别为x,y
如果x,y都在[1,sqrt(n)]范围内,则xy<n,与xy=n不符
如果x,y都在[sqrt(n),n]范围内,则xy>n,与xy=n不符
所以两个因子一定在两个不同的范围里
所以,只要从2搜到sqrt(n),就可以了
另外,搜出了一个因子之后可以直接break退出,不用继续搜下去(假如一个数是一个很大的质数*2,搜出2之后往后搜什么也搜不到,还会浪费时间
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int x,y;
cin >> x >> y;
int cnt=0;
if(x>y)
{
int t=x;
x=y;
y=t;
}
for(int i=x;i<=y;i++)
{
int f=1;
if(i==1)
{
continue;
}
for(int j=2;j<=i/j;j++)
{
if(i%j==0)
{
f=0;
break;
}
}
cnt+=f;
}
cout<<cnt;
return 0;
}
另外,还可以把判断质数过程提取出来,定义一个isPrime函数,这样就不用设一堆乱七八糟的f,直接在函数里判断即可
下面奉上带函数的代码:
#include <bits/stdc++.h>
using namespace std;
bool isPrime(int n)
{
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
return false;
}
}
return n>=2;
}
int main()
{
int x,y;
cin >> x >> y;
int cnt=0;
if(x>y)
{
int t=x;
x=y;
y=t;
}
for(int i=x;i<=y;i++)
{
cnt+=isPrime(i);
}
cout<<cnt;
return 0;
}
你以为结束了吗?不,这道题还有一种方法:
不知道大家还记不记得小学五年级下册第三单元:因数与倍数里面刚认识质数的时候,是不是有一张表,把2,3,5,7......的倍数划去?对,这就是第3种方法:埃氏筛法,这种方法比上一种快多了(上一种耗时164ms,这一种只要20ms,优势很明显了,数据再大一点比如大到6000000的时候就只能用这个了)
首先,定义一个数组,并假设里面全是质数(就是初始化为0,是合数的到时候改成1)
然后, 把0和1特判一下(改成1)
接着,从2遍历到y(不会超时的),如果是质数(0),就把它的倍数全改成合数(2倍开始!!!到y/i倍!太大要超!)
最后统计一下,然后输出即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
bool isPrime[1000005];
int main()
{
int x,y,cnt=0;
cin >> x >> y;
if(x>y)
{
int t=x;
x=y;
y=t;
}
isPrime[0]=isPrime[1]=1;
for(int i=2;i<=y;i++)
{
if(!isPrime[i])
{
for(int j=2;j<=y/i;j++)
{
isPrime[i*j]=1;
}
}
}
for(int i=x;i<=y;i++)
{
cnt+=!isPrime[i];
}
cout<<cnt;
return 0;
}
(第一题写了2133字)
第二题:B2138 最大质因子序列
题目描述
任意输入两个正整数 m,n(2≤m≤n≤5000),依次输出 m 到 n 之间每个数的最大质因子(包括 m 和 n;如果某个数本身是质数,则输出这个数自身)。
输入格式
一行,包含两个正整数 m 和 n,其间以单个空格间隔。
输出格式
一行,每个整数的最大质因子,以逗号间隔。
输入输出样例
输入 #1
5 10
输出 #1
5,3,7,2,3,5
思路:
既然是质因子,那就先打一个上面的判断质数函数,然后从n遍历到2,如果是质数而且是因数就输出然后跳出循环(我定义的是函数,一个return就行啦)
AC代码:
#include <bits/stdc++.h>
using namespace std;
bool flag;
bool isPrime(int n)
{
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
return false;
}
}
return n>=2;
}
void sss(int n)
{
for(int i=n;i>=2;i--)
{
if(isPrime(i)&&n%i==0)
{
if(!flag)
{
cout<<i;
flag=true;
return;
}
else
{
cout<<","<<i;
return;
}
}
}
}
int main()
{
int m,n;
cin >> m >> n;
for(int i=m;i<=n;i++)
{
sss(i);
}
return 0;
}
第三题:B2140 二进制分类
题目描述
若将一个正整数化为二进制数,在此二进制数中,我们将数字 1的个数多于数字 0 的个数的这类二进制数称为 A 类数,否则就称其为 B 类数。
例如:
(13)10=(1101)2,其中 1 的个数为 3,0 的个数为 1,则称此数为 A 类数;
(10)10=(1010)2,其中 1 的个数为 2,0 的个数也为 2,称此数为 B 类数;
(24)10=(11000)2,其中 1 的个数为 2,0 的个数为 3,则称此数为 B 类数;
程序要求:求出 1~n 之中(1≤n≤1000),全部 A,B 两类数的个数。
输入格式
输入 n。
输出格式
一行,包含两个整数,分别是 A 类数和 B 类数的个数,中间用单个空格隔开。
输入输出样例
输入 #1
7
输出 #1
5 2
思路:
定义一个函数判断是A类数还是B类数,统计个数,然后输出
AC代码:
#include <bits/stdc++.h>
using namespace std;
int A,B;
void sss(int n)
{
int c1=0,c2=0;
do
{
n%2?c1++:c2++;
n/=2;
}while(n);
if(c1>c2)
{
A++;
}
else
{
B++;
}
}
int main()
{
int n;
cin >> n;
for(int i=1;i<=n;i++)
{
sss(i);
}
cout<<A<<" "<<B;
return 0;
}
这篇博客就到这里啦,如果觉得好的话,就请点个赞或者点个收藏,关注吧!您的支持是我创作最大的动力!我写的很辛苦,就是为了你们的支持呀!(无辜)(眨眼)(o´・ェ・`o)本篇博客只有3道题,却有3380字!特别是第一道,共2133字呢!后面是因为我来不及了,只能这样了