题解_找素数

真·题·再·现

【题目描述】

恭喜王哲涵同学和姜昊志同学分别获得可达鸭十月月赛——基础赛第二场的第三名第五名的好成绩!
老师课堂上刚讲了数位分离和判断素数,就顺利成章的想找王哲涵同学和姜昊志同学搭档,王哲涵同学负责把n及以内的数据全都分离各个位,姜昊志同学负责统计这些位是素数的个数。
数位分离就是,把一个整数的各个位能单独分出来,比如一个数字是3241,单独分出数字3,数字2,数字4,数字1
判断素数的条件就是,一个数的因子只有1和它本身,比如一个数字7,它的因子只有17,也就是不能被其他数字整除。
例如:n=12n及以内的数据为:1,2,3,4,5,6,7,8,9,10,11,12,这些数据的各位分别是:1,2,3,4,5,6,7,8,9,1,0,1,1,1,2,这些数一共是5个素数。

【输入描述】

共有T组数据。
第一行,一个整数T,表示共有T组测试数据。
接下来T行,每行一个整数n,表示数位分离n及以内的数。

【输出描述】

T行,每行一个整数,表示分离n及以内的数所有位中出现的素数个数。

【输入样例】

2
12
30

【输出样例】

5
23

【数据范围】

对于100%的数据,1<=T<=1001<=n<=10000

解·题·思·路

【题目分析】

本题数据量较大,如果遍历1~n一个一个数位分离再找素数很浪费时间(大悲)。要解决这个问题,不能强夺,而事要智取(意味深)。

【解题过程】

他来了他来了,老三样他走来了!

using namespace std;
int main(){
}

题目要求将各位数字拆分后求质数,所以只需要求0~9的质数即可。

using namespace std;
int p[10]={0,0,1,1,0,1,0,1,0,0};//0~9的质数有2、3、5、7 
int main(){
}

主函数读入T,此时需要cstdio头文件。

#include<cstdio>
using namespace std;
int p[10]={0,0,1,1,0,1,0,1,0,0};//0~9的质数有2、3、5、7 
int main(){
	int t;
	scanf("%d",&t);//读入T 
}

接下来循环T次读入n,为了省一个循环变量,用while代替for

#include<cstdio>
using namespace std;
int p[10]={0,0,1,1,0,1,0,1,0,0};//0~9的质数有2、3、5、7 
int main(){
	int t,n;
	scanf("%d",&t);//读入T 
	while(t--){//为了省一个循环变量,用while代替for
		scanf("%d",&n);
	}
}

然后考虑读入n之后的输出,一定要预处理,不然多看一眼就会爆炸!!!(指爆零)
声明一个数组dp,用dp[i]表示读入的n=i时输出的数。
不难发现,当n=1时,输出的数为0,那么dp[1]=0n=2时,考虑数位分离判断质数,得出“状态转移方程”:dp[i]=dp[i-1]+solve(i),其中solve(i)表示数位分离的质数个数。

#include<cstdio>
using namespace std;
int dp[10086]={0,0};//将dp[1]初始化为0 
int p[10]={0,0,1,1,0,1,0,1,0,0};//0~9的质数有2、3、5、7
int SOLVE(int n){//整道题最费脑子的部分,这里最好写一个函数循环调用 
	int cnt=0;//声明一个cnt变量,记录数位分离后质数的个数
	while(n){
		cnt+=p[n%10];//如果n的个位是质数,将cnt增加1,否则不变
		n/=10;//将n的个位去掉,原数的十位即新数的个位 
	} 
	return cnt;//必须要有返回值,不然会被撅!!!(恼) 
} 
int main(){
	for(int i=2;i<10086;i++)dp[i]=dp[i-1]+SOLVE(i);//将SOLVE函数的值递推写入dp数组,注意这行代码必须放到主函数的开头,不然输出可能全0 
	int t,n;
	scanf("%d",&t);//读入T 
	while(t--){//为了省一个循环变量,用while代替for
		scanf("%d",&n);
		printf("%d",dp[n]);//输出dp[n]的值
		if(t)puts("");//puts()输出时会自动添加换行,注意括号里要有一对双引号,不然会被撅!!!(恼)
	}
	return 0;//这一句可有可无,但是某些比赛可能会有要求 
}

【测试结果】

全部样例均正确,以以有,阔以有!(赞赏)
谢谢观看!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值