这次头条笔试题比之前简单多了。。终于全部过了
-
找钱问题,共1024,64,16,4,1几种面值。因为1,4,16,64这几种面值都可以由小于他们的面值凑出来,所以直接贪心的选最大的面值就好。
import java.util.*; public class Main implements Runnable{ private final int mod = 1000000007, max = 200005; private final int [] arr = {64, 16, 4, 1}; public static void main(String[] args) { new Thread(null, new Main(), "thread-1", 1024*1024*10).start(); } @Override public void run() { try{ solve(); }catch (Exception e){ e.printStackTrace(); } } private void solve(){ Scanner cin = new Scanner(System.in); int N = 1024-cin.nextInt(), ans = 0; for(int i=0; i<4; i++){ ans += N/arr[i]; N %= arr[i]; } System.out.println(ans); } }
-
简单模拟。去掉三连重复(aaa)的最后一个,两对(aabb)的最后一个,而且符合最后匹配,所以直接从左开始模拟,两个bool,一个表示当前位前1,2位是否相等,另一个表示当前位的前2,3位是否相同。
import java.util.*; public class Main implements Runnable{ private final int mod = 1000000007, max = 200005; public static void main(String[] args) { new Thread(null, new Main(), "thread-1", 1024*1024*10).start(); } @Override public void run() { try{ solve(); }catch (Exception e){ e.printStackTrace(); } } private void solve(){ Scanner cin = new Scanner(System.in); int N = Integer.parseInt(cin.nextLine()); StringBuilder sb = null; for(int i=0; i<N; ++i){ sb = new StringBuilder(); String source = cin.nextLine(); boolean pIsDouble = false, ppIsDouble = false; int n = source.length(); char pre = ' '; for(int j=0; j<n; j++){ if(pIsDouble && source.charAt(j) == pre){ //三连 continue; }else if(!pIsDouble && ppIsDouble && source.charAt(j) == pre) {//两对 continue; }else{ ppIsDouble = pIsDouble; if(pre == source.charAt(j)){ pIsDouble = true; }else { pIsDouble = false; } pre = source.charAt(j); sb.append(source.charAt(j)); } } System.out.println(sb); } } }
-
发奖品问题。n个人的分数围成一个环,任何一个人获得的奖品数量都比左右两个分数比自己低的人多,分数相等的话没有要求,求最小需要多少个奖品。设dp[i]表示给i发的最小奖品,首先扫一遍数组,将两侧分数均比中间高的位置,奖品数置1,然后再扫一遍对没有赋值的位置进行递归记忆化搜索。复杂度O(N)
import java.util.*; public class Main implements Runnable{ private final int mod = 1000000007, max = 100005; int[] arr = new int[max], dp = new int[max]; public static void main(String[] args) { new Thread(null, new Main(), "thread-1", 1024*1024*10).start(); } @Override public void run() { try{ solve(); }catch (Exception e){ e.printStackTrace(); } } private void solve() { Scanner cin = new Scanner(System.in); int T = cin.nextInt(); for(int i=0; i<T; i++){ int n = cin.nextInt(); for(int j=0; j<n; j++){ arr[j] = cin.nextInt(); dp[j] = 0;//初始化dp数组 } for(int j=0; j<n; j++){ if(arr[(j+1)%n] >= arr[j] && arr[(j-1+n)%n] >= arr[j]){ // 最优情况下,这里发的奖品一定是1 dp[j] = 1; } } long ans = 0; for(int j=0; j<n; j++){ if(dp[j] == 0){ dfs(j, n); } ans += dp[j]; } System.out.println(ans); } } void dfs(int k, int n) { int pre = (k-1+n)%n, nex = (k+1)%n; if(arr[pre] < arr[k] && dp[pre] == 0){ dfs(pre, n); } if(arr[nex] < arr[k] && dp[nex] == 0){ dfs(nex, n); } if(arr[pre] < arr[k]){ dp[k] = Math.max(dp[k], dp[pre]+1); } if(arr[nex] < arr[k]){ dp[k] = Math.max(dp[k], dp[nex]+1); } } }
-
剪绳子问题。一根绳子可以任意裁剪,但是不能拼接。一共n根,要搞出来m条相等的绳子,且长度最长,结果保留两位小数。二分答案求最大值。复杂度O(nlog2^31)。
import java.util.*; public class Main implements Runnable{ private final int mod = 1000000007, max = 100005; int[] arr = new int[max]; public static void main(String[] args) { new Thread(null, new Main(), "thread-1", 1024*1024*10).start(); } @Override public void run() { try{ solve(); }catch (Exception e){ e.printStackTrace(); } } private void solve(){ Scanner cin = new Scanner(System.in); int n = cin.nextInt(),m = cin.nextInt(); double lower = 0D, higher = Integer.MAX_VALUE; for(int i=0; i<n; i++){ arr[i] = cin.nextInt(); } while(higher - lower > 0.001){ double mid = (lower+higher)/2; if(checkAns(n, m, mid)){ lower = mid; }else{ higher = mid; } } System.out.println(String.format("%.2f", lower)); } boolean checkAns(int n, int m, double mid){ int ans = 0; for(int i=0; i<n; i++){ ans += (int)arr[i]/mid; if(ans >= m){ return true; } } return false; } }