第一题
内容理解
给出两个整数n和k,在一个1到n的整数集合中,需要解题者通过删除最少的数,来达到集合中没有任意一个子集中的数相加等于k的效果。
输入
整数t,表示输入的案例个数,
整数n和k,其中
输出
输出t个案例的结果,每个结果格式如下
- 第一行输出一个整数,表示删除后的整个集合的长度(也就是含有多少个整数)
- 第二行输出若干个整数,表示删除后的集合中的所有元素
- 其中若对一种案例有多种结果,则输出一种即可
思路
对于这种题目,我们一般是想怎么样可以用一个比较万能的方法去删除,因为这里是子集中的数相加的和不呢为k,那我们不妨这样想:把那些足够小的数删掉不就可以了?那什么才叫足够小呢?我们用反向思维来想一下:找出一个子集,其中的数的和为k。若子集的长度为1,则数必须为k本身;若子集的长度为2,则有一个数小于k/2,另一个数大于k/2;若子集的长度更长,则数更多,更小的数也更多,值的分布有可能更不平均,但是我们可以找到一个共同点:按照这样的找法,子集长度大于等于2时,必然有小于k/2的数,而且把小于k/2的数全部删掉之后,剩余的数随便凑两个在一起都不等于k。
代码
import java.util.Scanner;
public class Anti_knapsack {
public static void main(String args[])
{
int n=0;
int k=0;
//输入
Scanner sc=new Scanner(System.in);
count=sc.nextInt();
for (int i=0;i<count;i++)
{
n=sc.nextInt();
k=sc.nextInt();
//直接判定删除后剩下的数
if(n==k)
System.out.println(k/2);
else
System.out.println(k/2+(n-k));
for (int j=k/2;j<=n;j++){
//这里就是判断应不应该输出k/2的部分,因为计算机的除法是直接取整,奇数k的k/2是能与k/2+1相加等于k的,而偶数k则不然
if (k%2==0&&j<k)
System.out.print(j+" ");
else if (j!=k&&j>k/2)
System.out.print(j+" ");
}
System.out.println();
}
}
}
第二题
内容理解
给出一个字符串s和一个数字k,要求判定s是否由2k+1个非空字符串以回文的形式组成(其中第1个到第k个拼接起来后,第k+1个可以是任何字符串,但是后面的k个字符串分别是第k到第1个的反转字符串)
输入
整数t,表示输入的案例个数,
整数n和k,n表示字符串长度,其中
输出
输出t行结果,每行格式:YES代表是,NO代表否
思路
想要找出k+1个非空字符串容易误解为:要从哪里分割?这样的分割方式会不会有问题?其实我们大可不必这样,题目要求找这么多,可没要求那k个字符串的长度,我们直接定为1不就可以了?完全没必要理会中间那第k+1个字符嘛!这样就转化为一个非常简单的判定问题了,只靠双指针循环遍历就可以解决
import java.util.Scanner;
public class Split_it {
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
//输入
int t;
t=sc.nextInt();
int n=0,k=0;
for(int i=0;i<t;i++)
{
int yes=1;
n=sc.nextInt();
k=sc.nextInt();
String s=sc.next();
//双指针判定
for(int j=0;j<k;j++)
{
char left=s.charAt(j);
char right=s.charAt(n-j-1);
if(left!=right||s.length()<=2*k) {//若不相等,或者字符串的长度不符合要求(连2k+1个字符串都没有)
yes = 0;
break;
}
}
if(yes==1)
{
System.out.println("yes");
}
else{
System.out.println("no");
}
}
}
}
“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情”