题一: 幸运数 思路:输入n,m两数(n<m),先将1~m的数字添加到List中,然后从幸运数2开始,将2到List.size()大小的数字中的下标能被幸运数2整取的数字添加到一个名为remove的List中,然后将remove中的数字作为list中的下标将list中对应的数字删除。
public class LuckyNum { public static void main(String[] args) { Scanner sc = new Scanner(System.in);//输入 int n = sc.nextInt(); int m = sc.nextInt(); List<Integer> list = new ArrayList<>(); for(int i=1;i<=m;i++){ list.add(new Integer(i)); } int luck = 2; //幸运数 int k = 1; //下标 List<Integer> remove = new ArrayList<>(); //等待被移除的数字 while(luck<=list.size()){ int cnt = 0;//代表list中目前删除了几个数字 for(int i=luck;i<=list.size();i++){ if(i%luck==0){ remove.add(i); } } for(int j=0;j<remove.size();j++){//将下标为remove中的数字移除 list.remove(remove.get(j)-(cnt++)-1); } remove.clear(); luck = list.get(k++); } //判断刚开始的mn是否在幸运数中 int count = 0; if(list.get(list.size()-1) == m) { count++; } if(list.get(0) == n) { count++; } System.out.println(list.size()-count); } }为什么不直接删除ArrayLis中的值,因为ArrayList有自动左移的功能,所以会导致下一次的寻值出错
题二: 最大不能凑成的数 思路:对于题中的两个数a和b,我们要找到一个上限n,对每个小于n的每个数进行判定与筛选。(设当前进行判定的数为m)如果m在减去i个a之后成为j个b乘积的形式,则我们需要将m减1。 比如对于4和7,我们需要找到一个数n(比如28),27-4=23-4=19-4=15-4=11-4=7=1*7,可以确定27不是我们要求的数,26-4=22-4=18-4=14=2*7,可以确定26不是我们要求的数。。。(减4和减7的情况是一样的,因为这个数一定是由4和7组成的)
那么问题来了,上限n怎么求? 所以我要要找到一个尽可能小,且每一个nm都有的一个数,且比这个数还大的数,都能被nm组成 所以答案为最小公倍数,a*b。 为什么是最小公倍数? 以29为例,如果28可以,那么29一定可以。因为2个4减去一个7等于1。也就是用两个4替换一个7。30也一定可以,因为可以用2个7替换3个4,以此类推。无论此时的数与最小公倍数m差多少,一定可以通过把i个4换成j个7的形式得到。但是如果反之则不一定成立,例如10,看似能减去2个7和1个4,凑成,但是10是无法由4和7构成的。
public class BuyNum { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int a = sc.nextInt(); int b = sc.nextInt(); int maxn = a*b; int[] vis = new int[maxn+1]; for(int i=0;i*a<=maxn;i++){ for(int j=0;j*b<maxn;j++){ if(i*a+j*b>maxn){//大于公倍数之后的值,无需计算 break; } vis[i*a+j*b] = 1;//大于公倍数的除去 } } for(int i=maxn;i>0;i--){ if(vis[i] == 0){ System.out.println(i); break; } } return; } }