备战蓝桥杯期间的题解,如有错误的地方,欢迎指正。
求质
题目链接:互质
问题描述
请计算在 [1,20232023] 范围内有多少个整数与2023 互质。由于结果可能很大,你只需要输出对 109+7取模后的结果
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
互质:如果两个或两个以上的整数的最大公约数是1,则称它们为互质
2023的因数有 [7,17,119,289],而119=7 * 17,289=17 * 17,所以只需要在20232023 中将7的倍数和17的倍数减去即可求出互质的个数。
7的倍数的个数:20232023/ 7
17的倍数的个数:20232023/ 17
7和17的共同倍数的个数(重复项):20232023/ (7 * 17)
所以互质个数 = 20232023 - (20232023/ 7 + 20232023/ 17 - 20232023/(7 * 17))
模运算规则、公式与基本四则运算类似,但是除法例外。其规则如下:
(a+b)%p=(a%p+b%p)%p
(a-b)%p=(a%p-b%p)%p
(a*b)%p=(a%p * b%p)%p
ab%p=((a%p)b)%p
根据模运算分配律得 互质个数%mod = 20232023 %mod - ((20232023/ 7)%mod + (20232023/ 17)%mod - (20232023/(7*17))%mod)%mod
令 a = 20232023 b = 7,则(20232023/ 7)%mod= (a/b)%mod。根据费马小定理和欧拉定理,如果b与mod互质,则 bmod-1 %mod = 1。
又 a/b = a * b-1,所以 (a/b) % mod = (a * b-1 * b(mod-1) %mod)%mod = (a %mod * b(mod-2)%mod)%mod。同理可以求出17倍数的个数和7和17的共倍数的个数。
代码
import java.util.*;
public class Main {
static int mod = (int)1e9+7;
public static void main(String[] args) {
long sum = qPow(2023,2023);
long ans = sum;
ans = (ans - sum * qPow(7,mod-2) + mod)%mod;
ans = (ans - sum * qPow(17,mod-2) + mod) % mod;
ans = (ans + sum * qPow(7*17,mod-2)) %mod;
System.out.println(ans);
}
public static long qPow(long a,long b){ // 快速求幂
long res =1;
a %= mod;
while(b > 0){
if ((b&1)==1){
res = res * a % mod;
}
a = a * a %mod;
b>>=1;
}
return res;
}
}
逆元
题目链接:逆元
问题描述
数论中的逆元是一个可以把除法转换为乘法的工具。若自然数 𝑎,Ia满足a × Ia ≡ 1(mod M),则称 a 在模M的意义下的逆元为Ia,这样在模M下计算除法时,可以把处以a的运算转化为乘以其逆元Ia。
给定质数模数 M = 2146516019,根据费马小定理对于不是M倍数的正整数a,有a(M-1) ≡ 1(mod M),求出 [1,233333333]内所有自然数的逆元。则所有逆元的异或和为多少?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
题目让求出[1,233333333]中的逆元。题目给出a(M-1) ≡ 1(mod M),a × Ia ≡ 1(mod M)
即 a(M-1) = a × Ia, 逆元Ia = a(M-2)
最后将[1,233333333]中的每个数进行逆元运算异或求和
代码
import java.util.*;
public class Main {
static int mod = 2146516019;
public static void main(String[] args) {
long res = qPow(1,mod-2);
for (int i = 2; i <= 233333333; i++) {
res ^= qPow(i,mod-2);
}
System.out.println(res);
}
public static long qPow(long a, long b) {
long res = 1;
a %= mod;
while(b > 0){
if((b&1)==1) {
res = res * a % mod;
}
a = a * a % mod;
b >>=1;
}
return res;
}
}
玩具
题目链接:玩具
问题描述
小明的妈妈给他买了n个玩具,但是为了同时考察他的智力,只给了他2 × n 个零件,第i个零件的重量为wi(1 <= i <= 2 × n)。
其中任意两个零件都可以拼接成一个玩具,这个玩具的权重就等于拼接所用的两个零件的重量的乘积。小明的妈妈希望小明能够使用这2 × n 个零件拼接出 n 个玩具(每个零件必须使用且只能用一次),使得所有玩具的权重的和最小。小明希望你帮帮他计算出最小的权重和。
输入描述
输入共2行
第一行为一个正整数 n
第二行为 2 × n 个空格隔开的整数 w1 ,w2,… w2×b,
输出描述
输出共1行,一个整数。
数据量很大,枚举不现实。用贪心的思想,模拟一些数据简单测试一下,发现最小值×最大值的时候和最小。
注意用long数组,有些数据很大
代码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long[] arr = new long[scan.nextInt()*2];
for (int i = 0; i < arr.length; i++) {
arr[i] = scan.nextInt();
}
Arrays.sort(arr);
long res = 0;
for (int i = 0; i < arr.length/2; i++) {
res += arr[i] * arr[arr.length-i-1];
}
System.out.println(res);
}
}
不完整的算式
题目链接:不完整的算式
问题描述
小蓝在黑板上写了一个形如 A op B = C 的算式,其中A、B、C都是非负整数,op是 +、-、、/(整除)四种运算之一。不过A、op、B、C这四部份有一部分被不小心的同学擦掉了。
给出这个不完整的算式,其中被擦掉的部分(被擦掉的部分是被完整的擦掉,不会出现留下若干位数字的情况)用?代替。请你输出被擦掉的部分。
输入描述
输入只有一行,包含一个字符串代表如上文所述的不完整的算式。
输出描述
如果被擦掉的部分是A、B、C之一,请输出一个整数代表答案。如果被擦掉的部分是op,请输出+、-、、/,四个字符之一代表答案。
这道题的思路是模拟。
这道题的难点是从字符串中确定A、op、B、C的位置。其实没有很难,只是比较繁琐。
首先定义四个变量as、op、bs、cs,遍历字符串,为as、op、bs、cs赋值,并且需要记录一下 “ ?” 出现的位置。
如果把求A和求B的代码合并的话,需要特别注意“/”运算。
代码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.next();
String as = "",ops="",bs="",cs="";
int flag = 0; // 求哪个数
// 找a
int i = 0;
// 第一个数
while(s.charAt(i) - '0' >= 0 && s.charAt(i)-'0' <= 9) {
i++;
}
if ( i == 0) {
i = 1;
flag = 1;
}
as = s.substring(0,i);
// 运算符
if (s.charAt(i) == '?'){
flag = 2;
}
ops = s.substring(i,i+1);
i++;
int l = i;
// 第二个数
while(s.charAt(i) - '0' >= 0 && s.charAt(i)-'0' <= 9) {
i++;
}
if (s.charAt(i) == '?'){
flag = 3;
i++;
}
bs = s.substring(l,i);
// 跳过 = 号
i++;
cs = s.substring(i);
if (cs.equals("?")){
flag = 4;
}
Long a,b,c;
if (flag == 1 || flag == 3){
if (flag == 1) {
b = Long.valueOf(bs);
}else {
b = Long.valueOf(as);
}
c = Long.valueOf(cs);
switch (ops){
case "+":
System.out.println(c-b);
break;
case "-":
System.out.println(c+b);
break;
case "*":
System.out.println(c/b);
break;
case "/":
if (flag == 1) {
System.out.println(c*b);
}else {
System.out.println(b/c);
}
break;
}
}
if (flag == 2) {
a = Long.valueOf(as);
b = Long.valueOf(bs);
c = Long.valueOf(cs);
if (a + b == c) {
System.out.println("+");
}else if (a - b == c){
System.out.println("-");
}else if (a * b == c) {
System.out.println("*");
}else if (a / b == c) {
System.out.println("/");
}
}
if (flag == 4) {
b = Long.valueOf(bs);
a = Long.valueOf(as);
switch (ops){
case "+":
System.out.println(a+b);
break;
case "-":
System.out.println(a-b);
break;
case "*":
System.out.println(a*b);
break;
case "/":
System.out.println(a/b);
break;
}
}
}
}
ps:没有后面是因为菜