问题描述
令 S = 1! + 2! + 3! + … + 202320232023!,求 S 的末尾 9 位数字。
提示:答案首位不为 0。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这道题肯定不能按题目的要求算到 202320232023!,肯定有规律可循,所以不妨先算前50项,取最后9位看看结果。阶乘算出来的结果很大,用Long也会爆,可以用BigIneger,需要注意的是BigInteger的加减乘除需要调API实现。
import java.math.BigInteger;
public class 试题A_阶乘求和 {
public static void main(String[] args) {
BigInteger n=new BigInteger("1");
BigInteger sum=new BigInteger("0");
for(int i=1;i<50;i++) {
n=n.multiply(new BigInteger(""+i));
sum=sum.add(n);
System.out.println("i="+i+"时,sum后九位是:"+sum.mod(new BigInteger(""+1000000000)));
}
}
}
结果可以发现,从第39项开始,最后9位数字就没有变化了,所以答案就是420940313
问题描述
哈沙德数是指在某个固定的进位制当中,可以被各位数字之和整除的正整数。例如 126 是十进制下的一个哈沙德数,因为 (126)10 mod (1+2+6) = 0;126也是八进制下的哈沙德数,因为 (126)10 = (176)8,(126)10 mod (1 + 7 + 6) = 0;同时 126 也是 16 进制下的哈沙德数,因为 (126)10 = (7e)16,(126)10 mod (7 + e) = 0。小蓝认为,如果一个整数在二进制、八进制、十进制、十六进制下均为哈沙德数,那么这个数字就是幸运数字,第 1 至第 10 个幸运数字的十进制表示为:1 , 2 , 4 , 6 , 8 , 40 , 48 , 72 , 120 , 126 . . . 。现在他想知道第 2023 个幸运数字是多少?你只需要告诉小蓝这个整数的十进制表示即可。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这道题目单纯考察进制转换,调用Java现成的API即可:
十进制转二进制:Integer.toBinaryString(i)
十进制转八进制:Integer.toOctalString(i)
十进制转十六进制:Integer.toHexString(i)
求数位之和要注意:十六进制字符串可能包含a-f,所以需要特殊处理。
public class 试题B_幸运数字 {
//求一个数字字符串的数位之和
public static int getSum(String s) {
int sum=0;
for(int i=0;i<s.length();i++) {
if(s.charAt(i)>='a'&&s.charAt(i)<='f') //如果是a-f
sum+=s.charAt(i)-'a'+10;
else //如果是数字
sum+=s.charAt(i)-'0';
}
return sum;
}
public static void main(String[] args) {
int count=0;
for(int i=1;i<1000000;i++) {
String a2=Integer.toBinaryString(i); //转为二进制
String a8=Integer.toOctalString(i); //转为八进制
String a16=Integer.toHexString(i); //转为十六进制
if(i%getSum(a2)==0&&i%getSum(a8)==0&&i%getSum(a16)==0&&i%getSum(""+i)==0) {
count++;
if(count==2023) {
System.out.println("第 2023 个幸运数字是:"+i);
break;
}
}
}
}
}
第 2023 个幸运数字是:215040
问题描述
小蓝有一个长度为 N 的数组 A = [A0, A1, . . .,AN−1]。现在小蓝想要从 A 对应的数组下标所构成的集合 I = {0, 1, 2, . . . , N − 1} 中找出一个子集 R1,那么 R1在 I 中的补集为 R2。记 S1 = ∑ r ∈ R1 Ar,S2 = ∑ r ∈ R2 Ar,我们要求 S1 和 S2 均为偶数,请问在这种情况下共有多少种不同的 R1。当 R1 或 R2 为空集时我们将S 1 或 S 2 视为 0。
输入格式
第一行一个整数 T,表示有 T 组数据。
接下来输入 T 组数据,每组数据包含两行:第一行一个整数 N,表示数组A 的长度;第二行输入 N 个整数从左至右依次为 A0, A1, . . . , AN−1,相邻元素之间用空格分隔。
输出格式
对于每组数据,输出一行,包含一个整数表示答案,答案可能会很大,你需要将答案对 1000000007 进行取模后输出。
样例输入
2
2
6 6
2
1 6
样例输出
4
0
样例说明
对于第一组数据,答案为 4。(注意:大括号内的数字表示元素在数组中的下标。)
R1 = {0}, R2 = {1};此时 S 1 = A0 = 6 为偶数, S 2 = A1 = 6 为偶数。
R1 = {1}, R2 = {0};此时 S 1 = A1 = 6 为偶数, S 2 = A0 = 6 为偶数。
R1 = {0, 1}, R2 = {};此时 S 1 = A0 + A1 = 12 为偶数, S 2 = 0 为偶数。
R1 = {}, R2 = {0, 1};此时 S 1 = 0 为偶数, S 2 = A0 + A1 = 12 为偶数。
对于第二组数据,无论怎么选择,都不满足条件,所以答案为 0。
评测用例规模与约定
对于 20% 的评测用例,1 ≤ N ≤ 10。
对于 40% 的评测用例,1 ≤ N ≤ 102。
对于 100% 的评测用例,1 ≤ T ≤ 10, 1 ≤ N ≤ 103, 0 ≤ Ai ≤ 109。
这道题我想到的是暴力解法。对于所给数组A(元素可重复),用回溯法求解出其所有的子集R1,将数组A的元素和 - 子集R1的元素和,即得到补集R2的元素和,然后判断是否满足条件。
注意:将答案对 1000000007 进行取模后输出
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
// 子集类
class SubSet{
List<List<Integer>> res=new LinkedList<List<Integer>>();//存储所有子集
LinkedList<Integer> track=new LinkedList<Integer>(); //存储一个子集
boolean[] used; //记录是否访问过
// 求出所有子集
List<List<Integer>> subset(int[] nums){
used=new boolean[nums.length];
backtrack(nums, 0);
return res;
}
// 回溯法求子集
void backtrack(int[] nums,int start) {
res.add(new LinkedList<Integer>(track));
//回溯框架
for(int i=start;i<nums.length;i++) {
//不用剪枝,可以重复
// if(i>start&&nums[i]==nums[i-1]&&!used[i-1]))
// continue;
//选择
used[i]=true;
track.add(nums[i]);
//进入下一层回溯
backtrack(nums, i+1);
//撤销选择
track.removeLast();
used[i]=false;
}
}
}
public class 试题C_数组分割 {
//返回一个列表的所有数字的和
public static int getSum(List<Integer> nums) {
int sum=0;
for(int e:nums)
sum+=e;
return sum;
}
//统计满足条件的R1个数
public static int count(int[] A) {
SubSet subSet=new SubSet();
List<List<Integer>> resList=subSet.subset(A);
int count=0; //统计满足情况的R1个数
for(List<Integer> R1:resList) {
//将数组A转为List
List<Integer> listA=Arrays.stream(A).boxed().collect(Collectors.toList());
//R1的补集R2的元素和S2
int S2=(getSum(listA)-getSum(R1))%2;
if(getSum(R1)%2==0&&S2==0)
count++;
}
return count%1000000007;
}
public static void main(String[] args) {
//输入
Scanner sc=new Scanner(System.in);
int T=sc.nextInt(); //有T组数据
int[] res=new int[T]; //记录每组数据的结果
for(int i=0;i<T;i++) {
int N=sc.nextInt();
int[] A=new int[N]; //存放每组数据
for(int j=0;j<N;j++) {
A[j]=sc.nextInt();
}
res[i]=count(A);
}
for(int i=0;i<T;i++) {
System.out.println(res[i]);
}
}
}