1094-谷歌的招聘(PAT-B)

本文介绍了一种算法,用于从任意长度的数字串中查找最早的K位连续数字组成的素数。文章详细阐述了如何使用字符串存储长整数,如何提取连续的K位数字,并通过判断素数的函数来确定解决方案。

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

题目如下:

本题要求你编程解决一个更通用的问题:从任一给定的长度为 L 的数字中,找出最早出现的 K 位连续数字所组成的素数。
输入格式:

输入在第一行给出 2 个正整数,分别是 L(不超过 1000 的正整数,为数字长度)和 K(小于 10 的正整数)。接下来一行给出一个长度为 L 的正整数 N。
输出格式:

在一行中输出 N 中最早出现的 K 位连续数字所组成的素数。如果这样的素数不存在,则输出 404。注意,原始数字中的前导零也计算在位数之内。例如在 200236 中找 4 位素数,0023 算是解;但第一位 2 不能被当成 0002 输出,因为在原始数字中不存在这个 2 的前导零。
输入样例 1:

20 5
23654987725541023819
输出样例 1:

49877
输入样例 2:

10 3
2468024680
输出样例 2:

404

解决方法:

1.思路:
(1)要处理的数据是一个长度不超过1000位的正整数,很明显,应该使用字符串来存取这个数据。
(2)既然需要输出的是最早出现的由K位数字组成的素数,那么首先就应该先把这些K位数字组成的数找出来,接着从这些数中找到第一个出现的素数,最后输出。
有了思路,就只需要解决用字符串存储数据,寻找K位数字组成的数,判断是否为素数这三个主要问题就可以解出这个题。
2.使用字符串存取数据:
当整数的位数很大时,就应该使用字符串来存取数据了,将每一位数字都存入一个字符串数组元素中,如果题目需要使用int型数据的时候,将字符型数据减去0对应的ASCII码值即可得到整型数值(即 - ’ 0 ')。
3.寻找K位数字:
如果对C++不是很熟悉的话,那么就应该老老实实的使用双层循环来实现找到K位数字的数。
如下:

//len为整数的长度,m为连续K位数字的位数K
for(int i = 0; i < len - m + 1; i++)
{
		for(int j = i; j < i + m; j++) {}
}

外层循环的作用是使得循环从第一位开始到第len - m + 1位结束,内层循环的作用则是由第i位开始连续取m位数字。按照题目的例子来说:
20 5
23654987725541023819
len是20,m是5,那么这些数字就应该从第一位2开始,连续5位数字:23654,接着到3,连续5位数字:36549,接着65498…一直到第16位2开始的五位数字23819。特别的要注意这里是第16位数字截止的而不是第15位数字截止。这就是外循环上限是len - m + 1的原因。

如果对C++很熟悉的话,C++的string类中有个函数substr,可以实现以上功能。

substr:

  1. 用途:一种构造string的方法
  2. 形式:s.substr(pos, n)
  3. 解释:返回一个string,包含s中从pos开始的n个字符的拷贝(pos的默认值是0,n的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
  4. 补充:若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾
#include<string>
#include<iostream>
using namespace std;
int main()
{
  string s("12345asdf");
  string a = s.substr(0,5);     //获得字符串s中从第0位开始的长度为5的字符串
  cout << a << endl;
}
//输出结果为:12345

虽然现在已经将数字找出来了,可是这个数字目前还是字符串类型的,并不是整型,所以接着必须把他们变成整型,因为保存数字用的是字符串数组,将字符串数组的每一位减去0的ASCII码值即可得到这个数字,然而题目要求的是连续数字,所以需要把他们加起来,这时就需要用到函数pow,利用pow得到10的幂次方,将10的幂次方对应个十百千位相乘再相加,就得到了数字(例如23654 = 20000 + 3000 + 600 + 50 + 4)。如果觉得以上方法繁琐的话,可以使用C++函数atoi,直接就可以将string类型转换为int类型。
按照以上思路,就可以写代码了:

	int sum[n - m + 1] = {0}; 
	 //首先创立一个数组来保存得到的数字,这个数组的大小应该和外循环的上限是一样的。 
	int flag; 
	 //因为需要实现10的幂次方的降幂,所以需要一个变量来控制幂次
	int number;  
	//最后将string类型的数据减去ASCII码值后得到的整数赋值给number,由他来进行相关的计算。
	
	//第一步得到string字符串的长度
	int len = str.length();
	//第二步开始循环
	for(int i = 0; i < len - m + 1; i++) {
	    //首先给10的幂次设定上限,因为是m位数,所以高位肯定是10的m - 1次方
		flag = m - 1;  
		for(int j = i; j < i + m; j++) {
			number = str[j] - '0';
		    sum[i] += number * pow(10, flag);
			flag--;
		}
	}

或者是:

    for(int i = 0; i < len - m + 1;i++) {
        int number;
        string s=str.substr(i,K);
        number=atoi(s.c_str());
    }

4.判断素数
通过判断n能否被从2到根号n中的任何一个整数整除来判断是否为素数

bool isPrime(int n) 
{
	if(n <= 1) return false;
	int sqr = sqrt(1.0 * n);
	for(int i = 2; i <= sqr; i++){
		if(n % i == 0) return false;
	}
	return true;
}

完整代码:

#include <iostream>
#include <algorithm>
#include <math.h>
#include <iomanip>
using namespace std;
bool isPrime(int n) 
{
	if(n <= 1) return false;
	int sqr = sqrt(1.0 * n);
	for(int i = 2; i <= sqr; i++){
		if(n % i == 0) return false;
	}
	return true;
}
int main() 
{
	string str;
	int n,m; 
	cin >> n >> m;
	cin >> str; 
	int sum[n - m + 1] = {0};  
	int flag;
	int number;
	int times = 0;
	int len = str.length();
	for(int i = 0; i < len - m + 1; i++) {
		flag = m - 1;
		for(int j = i; j < i + m; j++) {
			number = str[j] - '0';
		    sum[i] += number * pow(10, flag);
			flag--;
		}
	}
	for(int i = 0; i < len - m + 1; i++) {
		if(isPrime(sum[i]) == true) {
			cout << setfill('0') << setw(m) << sum[i] << endl;//前面自动补0 
			times++;
			break;
		}
	}
	if(times == 0) cout << "404";
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值