1.计数问题。国王要给A,B两个国家分土地,有1...n块土地,输入两个国家想要的土地编号,输出只有A国想要的土地数,只有B国想要的土地数,以及两个国家都想要的土地数。
样例
输入
n=3
A=[1,2,3]
B=[3,4,5]
输出:2 2 1
思路:建立HashSet首先对A想要的土地进行遍历并逐一加入HashSet,然后从B的第一个土地开始判断是否有重合(即两个国家都想要的土地),并统计重合的数量。对于只有A要的土地,用A土地的总数量减去两者重合土地的数量即为只有A想要的土地数量。同理B的计算也是一样
public class MT1 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String firstline=in.nextLine();
String first[]=firstline.split(" ");
String p_s=in.nextLine();
String q_s=in.nextLine();
String a[]=p_s.split(" ");
String b[]=q_s.split(" ");
int res1=0,res2=0,res3=0;
Set<Integer> set=new HashSet<Integer>();
for(int i=0;i<a.length;i++) {
set.add(Integer.parseInt(a[i]));
}
for(int j=0;j<b.length;j++) {
if(set.contains(Integer.parseInt(b[j]))) {
res3++;
}
}
res1=a.length-res3;res2=b.length-res3;
System.out.print(res1+" "+res2+" "+res3);
}
}
2.计数问题。 给一串偶数个字符,只有大小写字母,问最小修改多少个字母使得字符串中大小写数量相同。
样例
输入
“AAAb”
输出
1 (如AAbb,AbAb等,这里不关心修改后的字符串是什么)
思路:分别统计大小写字母的数量,假设分别为A和B,最小修改字母=(A+B)/2-min(A,B)
import java.util.Scanner;
public class MT2 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String firstline=in.nextLine();
char[]s=firstline.toCharArray();
int x_num=0; int X_num=0;
for(int i=0;i<s.length;i++) {
if(s[i]<='Z'&&s[i]>='A') {
X_num++;
}else {
x_num++;
}
}
int min=Math.min(x_num, X_num);
System.out.println((x_num+X_num)/2-min);
}
}
3.异或运算问题。输入数组A=,定义数组B为
,求
的取值,其中
为异或运算。
样例
输入
2
3 2
输出
0
解释:
异或性质:(1)将两数异或的结果与其中一数再进行异或,可以得到另一个数(交换律 a^b^a=a^a^b=0^b=b)。(2)与0相异或,保留原值 。(3)一个数与另一个数异或两次是其本身 。(4)任何数异或自身为零。
如果直接采用公式去求解(暴力法),只能AC55%,因此必须分析该式子呈现的规律。
举例分析:假设n=8,那么我们将最后的公式乘积用下图的表格表示,后面的矩阵表示对应位置取模后的值(i mod j)
i/j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ||
b1= | a1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
b2= | a2 | 2 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 2 |
b3= | a3 | 3 | 0 | 1 | 0 | 3 | 3 | 3 | 3 | 3 |
b4= | a4 | 4 | 0 | 0 | 1 | 0 | 4 | 4 | 4 | 4 |
b5= | a5 | 5 | 0 | 1 | 2 | 1 | 0 | 5 | 5 | 5 |
b6= | a6 | 6 | 0 | 0 | 0 | 2 | 1 | 0 | 6 | 6 |
b7= | a7 | 7 | 0 | 1 | 1 | 3 | 2 | 1 | 0 | 7 |
b8= | a8 | 8 | 0 | 0 | 2 | 0 | 3 | 2 | 1 | 0 |
对图表进行观察可以发现,对于每一列上的数字,取值都是0到j-1范围内并一直循环。根据异或运算的性质,任何数异或本身为0,那么对于每一列我们可以提前进行异或运算得出值,并对每一列的值进行异或运算,最后继续对^a1^....^an进行异或即可。
对于每一列j上的数进行异或的情况分为以下2种:
(1)n/j的商为奇数。对(n%j)+1到j-1之间的值进行异或运算
(2)n/j的商为偶数
1)n%j==0,即能被j整除,则跳过该列的计算
2)n%j!=0,则对1到n%j之间的值进行异或运算
public class MT3 {
//异或运算
public static void main(String[] args) {
Scanner in=new Scanner(System.in); //暴力法 会超时
int firstnum=Integer.parseInt(in.nextLine());
String firstline=in.nextLine();
String a[]=firstline.split(" ");
int res=0;
for(int i=0;i<a.length;i++) { //计算a1^....an
res^=Integer.parseInt(a[i]);
}
//直接算每列异或后的结果
for(int j=1;j<a.length+1;j++) {
if((a.length/j)%2!=0) { //如果n除以j的商为奇数
int temp=a.length%j;
for(int k=temp+1;k<j;k++) {
res^=k;
}
}else { //商为偶数 余数为0则跳过
if(a.length%j!=0) {
int temp=a.length%j;
for(int k=1;k<=temp;k++) {
res^=k;
}
}
}
}
System.out.println(res);
}
4.员工下属问题。