蓝桥杯省赛7日集训-简单数论 - 蓝桥云课
目录
第一题:质因数分解
题目描述
输入描述
输出描述
输入输出样例
运行限制
题目 分析
一个质因数分解的模板——与第六题相识
题目代码
第二题:质数
题目描述
输入描述
输出描述
输入输出样例
运行限制
题目分析
题目代码
第三题:小数第n位
题目描述
输入描述
输出描述
输入输出样例
运行限制
题目分析
难点:如何获得小数部分
题目代码
第四题:棋盘放麦子
题目描述
运行限制
题目分析
题目代码
第五题: 等差数列
题目描述
输入描述
输出描述
输入输出样例
运行限制
题目分析
题目代码
第六题:数数
问题描述
答案提交
运行限制
题目分析
题目代码
第七题:约数个数
题目描述
运行限制
题目分析
题目代码
第八题: 质数拆分
题目描述
运行限制
题目分析
题目代码
题目描述
已知正整数 n 是两个不同的质数的乘积,试求出较大的那个质数。
输入描述
输入只有一行,包含一个正整数 6≤n≤2×10^9。
输出描述
输出只有一行,包含一个正整数 p,即较大的那个质数。
输入输出样例
示例
输入
21
输出
7
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
题目 分析
/**
* 分解质因数只针对合数
* 先用一个合数的最小质因数去除这个合数,得出的数若是一个质数,就写成这个合数相乘形式;
* 若是一个合数就继续按原来的方法,直至最后是一个质数 。
*/因为质因数可能重复,所以应用while,重复判断质因数
一个质因数分解的模板——与第六题相识
static int judge(int n) { int count = 0; for (int i = 2; i <= Math.sqrt(n); i++) { while (n % i == 0) { count++;//质因数+1 n = n / i; } } if (n > 1) count++; return count; }
不要忘记最后n>1的情况
if (n > 1) count++;
题目代码
import java.util.HashSet; import java.util.Scanner; /** * 分解质因数只针对合数 * 先用一个合数的最小质因数去除这个合数,得出的数若是一个质数,就写成这个合数相乘形式; * 若是一个合数就继续按原来的方法,直至最后是一个质数 。 */ public class 质因数分解 { public static void main(String[] args) { Scanner sca = new Scanner(System.in); long n = sca.nextInt(); HashSet
set = new HashSet<>(); //已知正整数n 是两个不同的质数的乘积,试求出较大的那个质数。 //只需要到sqrt(n)即可,因为如果有一个因数大于等于sqrt(n),那么必定有一个因数小于等于sqrt(n) for (long i = 2l; i <= Math.sqrt(n); i++) //分解质因数:从最小的质因数遍历, { while (n % i == 0) //因为质因数可能重复,所以应用while,重复判断质因数 9==3*3 { set.add(i); n = n / i; //n改变 } } //特别注意最后n%i!=0的时候如果n>1,n也是一个质因数要加上 //比如 21 = 3 * 7 (21/3==7、7%3!=0) if (n > 1) set.add(n); long max = 0; for (Long i : set) { if (i > max) max = i; } System.out.println(max); } }
题目描述
给定一个正整数 N,请你输出 N 以内(不包含 N)的质数以及质数的个数。
输入描述
输入一行,包含一个正整数 N。1≤N≤10^3
输出描述
共两行。
第 11 行包含若干个素数,每两个素数之间用一个空格隔开,素数从小到大输出。
第 22 行包含一个整数,表示N以内质数的个数。
输入输出样例
示例
输入
10
输出
2 3 5 7 4
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
题目分析
就一个判断质数
1)直观判断法改进
对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数。
原文链接:https://blog.csdn.net/huang_miao_xin/article/details/51331710
题目代码
import java.util.Scanner; public class 质数 { public static void main(String[] args) { Scanner sca = new Scanner(System.in); int n = sca.nextInt(); int count =0; for (int i = 2; i < n; i++) { if (judge(i)) { count++; System.out.print(i+" "); } } System.out.println(); System.out.println(count); } static Boolean judge(int n) { if (n<=0){ return false; } for (int i = 2; i <=Math.sqrt(n); i++) { if (n % i == 0) { return false; } } return true; } }
题目描述
我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数。
如果我们把有限小数的末尾加上无限多个 0,它们就有了统一的形式。
本题的任务是:在上面的约定下,求整数除法小数点后的第 n 位开始的 3 位数。
输入描述
输入一行三个整数:a b n,用空格分开。a 是被除数,b 是除数,n 是所求的小数后位置(0
输出描述
输出一行 3 位数字,表示:a 除以 b,小数后第 n 位开始的 3 位数字。
输入输出样例
示例
输入
1 8 1
输出
125
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
题目分析
难点:如何获得小数部分
第 n 位的后三位,也就是第 n ------ n + 2 位,把第 n + 2 位(含)之前的部分变成整数,再%1000就是我们要的三位数答案,最小的位是第 n + 2 位,想把它变成整数的个位,需要 乘 10n+2 ,也就是 a / b * 10^(n+2) % 1000 即为答案,因为 n 的范围可能很大,所以就需要用快速幂取模算法 。
想了解快速幂取模算法看下面链接
蓝桥杯--历届试题 小数第n位(java)_x/d%m=x%(d脳m)/d_码畜也有梦想的博客-CSDN博客
题目代码
import java.util.Scanner; public class 小数第n位 { public static void main(String[] args) { Scanner sca = new Scanner(System.in); double a = sca.nextDouble(); double b = sca.nextDouble(); int n = sca.nextInt(); int temp = (int)Math.floor((a/b)*Math.pow(10,n+2)); int res = temp%1000; System.out.println(res); } }
不是满分代码
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
你一定听说过这个故事。国王对发明国际象棋的大臣很佩服,问他要什么报酬,大臣说:请在第 1 个棋盘格放 1 粒麦子,在第 2 个棋盘格放 2 粒麦子,在第 3 个棋盘格放 4 粒麦子,在第 4 个棋盘格放 8 粒麦子,......后一格的数字是前一格的两倍,直到放完所有棋盘格(国际象棋共有 64 格)。
国王以为他只是想要一袋麦子而已,哈哈大笑。
当时的条件下无法准确计算,但估算结果令人吃惊:即使全世界都铺满麦子也不够用!
请你借助计算机准确地计算,到底需要多少粒麦子。
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
题目分析
java中最大范围是64位 long 型整数 题目中还是不够
用java.math.BigInteger 可以用来表示任意大小的整数
常用的两种定义方式
BigInteger a=new BigInteger("123"); //没有参数为long的构造函数,用字符串来构造
BigInteger b=BigInteger.valueOf(123); //静态方法,返回val对应的BigInteger
BigInteger类中定义了四则运算的方法,add,subtract,multiply,divide。对 BigInteger 做运算的时候,只能使用实例方法。
如:
a=a.add(b);
题目代码
import java.math.BigInteger; public class 棋盘放麦子 { public static void main(String[] args) { BigInteger sum = BigInteger.valueOf(1); BigInteger add = BigInteger.valueOf(1); BigInteger mul = BigInteger.valueOf(2); for (int i = 0; i < 63; i++) { add = add.multiply(mul);//*2 sum = sum.add(add);//+ } System.out.print(sum); } }
题目描述
数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一 部分的数列,只记得其中 N 个整数。
现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有几项?
输入描述
输入的第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,⋅⋅⋅,AN。(注意 A1 ∼ AN 并不一定是按等差数列中的顺序给出)
其中,2≤N≤10^5,0≤Ai≤10e9。
输出描述
输出一个整数表示答案。
输入输出样例
示例
输入
5 2 6 4 10 20
输出
10
样例说明: 包含 2、6、4、10、20 的最短的等差数列是 2、4、6、8、10、12、14、16、 18、20。
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
题目分析
注意一下公差为0的时候
题目代码
import java.util.Arrays; import java.util.Scanner; public class 等差数列 { public static void main(String[] args) { Scanner sca = new Scanner(System.in); int n = sca.nextInt(); int[] arr = new int[n]; for (int i = 0; i < n; i++) { arr[i] = sca.nextInt(); } Arrays.sort(arr); int min = Integer.MAX_VALUE; for (int i = 1; i < n; i++) {//找最小公差 if (arr[i] - arr[i - 1] < min) { min = arr[i] - arr[i - 1]; } } int a = arr[0]; int count =0 ; if (min==0){//公差为0 System.out.println(arr.length); return; } while (true) { if (a > arr[arr.length - 1]) { break; } count++; a = a + min; } System.out.println(count); } }
问题描述
任何一个大于 1 的正整数都能被分解为若干个质数相乘, 比如 28=2×2×7 被分解为了三个质数相乘。请问在区间 [2333333, 23333333] 中有多少个正整数 可以被分解为 12 个质数相乘?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。
运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
题目分析
直接套 质因数分解模板
static int judge(int n) { int count = 0; for (int i = 2; i <= Math.sqrt(n); i++) { while (n % i == 0) { count++;//质因数+1 n = n / i; } } if (n > 1) count++; return count; }
题目代码
public class 数数 { public static void main(String[] args) { int res = 0; for (int i = 2333333; i <= 23333333; i++) { if (judge(i) == 12) { res++; } } System.out.println(res); } static int judge(int n) { int count = 0; for (int i = 2; i <= Math.sqrt(n); i++) { while (n % i == 0) { count++;//质因数+1 n = n / i; } } if (n > 1) count++; return count; } }
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
1200000 有多少个约数(只计算正约数)。
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
题目分析
只需注意1也为n的因数即可(1不是质数)
题目代码
public class 约数个数 { public static void main(String[] args) { int n = 1200000; int count =0; for (int i = 1; i <= Math.sqrt(1200000); i++) { if (n%i==0){ count = count+2; } } if (Math.sqrt(n)*Math.sqrt(n)==n){ count--; } System.out.println(count); } }
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
将 20192019 拆分为若干个两两不同的质数之和,一共有多少种不同的方法?
注意交换顺序视为同一种方法,例如 2+2017=2019 与 2017+2=2019 视为同一种方法。
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
题目分析
01背包问题
蓝桥杯学习——01 背包_蓝桥杯01背包_小卢先冲的博客-CSDN博客
题目代码
// 1:无需package // 2: 类名必须Main, 不可修改 public class Main { static int n = 2500; static int[] arr = new int[n];//存放质数 static long dp[][] = new long[n][n];//记录方案数 public static void main(String[] args) { int cur = 1; //307 2-2019有307个质数 for (int i = 2; i < 2019; i++) { if (ispre(i)) { arr[cur++] = i; } } //开始01背包 dp[0][0] = 1;//容量为0也是一种方案 for (int i = 1; i < cur; i++) { //[物品]质数个数 for (int j = 0; j <= 2019; j++) { //[背包容量]最小为0,所以从0开始 dp[i][j] = dp[i - 1][j]; //不选i的情况,填充上一个 if (arr[i] <= j) { //是否超过当前背包总容量 /** * 按01背包的术语来讲 arr[i]就是存进j背包花费的空间!! 这边价值总和就是2019 * 这个状态转移方程 与当前行无关,与上一行有关 * f[ i] [j]=max(f [i−1] [j],f[i−1] [j−c[i]]+w[i]) * 这里直接 f[i][j] = f[i-1][j-c[i]]了 */ dp[i][j] += dp[i - 1][j - arr[i]]; //如果当前能容下i 选第i个数 //dp[1][2] += dp[0][0](1) = 2; dp[1][3] += dp[0][1]; //dp[2][5] += dp[1][2](2) = 3 } } } System.out.println(dp[cur - 1][2019]); } public static boolean ispre(int n) { for (int i = 2; i <= Math.sqrt(n); i++) { if (n % i == 0) { return false; } } return true; } }