赞
踩
目录
答案:3181
思路:num数组记录0-9的个数,从1开始判断,如果数字的各位中含有字母c,则num[c]减1,直至最后num[c]<0,则不能凑出。
- public class Main {
- public static void main(String[] args) {
-
- int [] num = {2021,2021,2021,2021,2021,2021,2021,2021,2021,2021} ;
- for(int i=1; ; i++){
- String s = String.valueOf(i) ;
- for(int j=0; j<s.length(); j++){
- int c = s.charAt(j) - '0' ;
- num[c] -- ;
- if(num[c]<0){
- System.out.println(i-1);
- return ;
- }
- }
- }
- }
- }
答案:17812964
思路:枚举+判断即可。
- public class Main {
- public static void main(String[] args) {
-
- for(long i=1; i<=1000000007; i++){
- if((i * 2021)%1000000007==999999999){
- System.out.println(i);
- return ;
- }
- }
- System.out.println(0);
- }
- }
答案:40257
思路:这题并不太容易想到,其实就是枚举所有点,判断对应的斜率和截距组成的不同坐标的个数,可以用set自动去重。
公式:y-y1=(y2-y1)/(x2-x1)*(x-x1)
故:k=(y2-y1) / (x2-x1) ; b=(x2*y1-x1*y2)/(x2-x1)
-
- import java.util.Set;
- import java.util.TreeSet;
-
- public class Main {
- public static void main(String[] args) {
- Set<String> set = new TreeSet<>() ;
- double k, b ;
- for(int x1=0; x1<20; x1++){
- for(int y1=0; y1<=20; y1++){
- for(int x2=x1+1; x2<20; x2++){
- for(int y2=0; y2<=20; y2++){
- k = 1.0 * (y2 - y1) / (x2 - x1) ;
- b = 1.0 * (x2 * y1 - x1 * y2) / (x2 - x1) ;
- set.add(k+","+b) ;
- }
- }
- }
- }
- System.out.println(set.size()+20); //要加上斜率不存在的20个
- }
- }
答案:10266837
思路:单源最短路径,Dijkstra算法,建立邻接表,如果节点之差绝对值小于等于21,建立边,对应的边权值为两节点值得最小公倍数,dist数组记录到达相应节点得最短路径,通过优先队列按照权值最小排序,每次选择更小得路径 ,更新当前路径。
- import java.util.ArrayList;
- import java.util.List;
- import java.util.PriorityQueue;
-
- public class Main{
- public static void main(String[] args) {
- List<int []> g[] = new List [2022] ;
- for(int i=0; i<2022; i++){
- g[i] = new ArrayList<>() ;
- }
-
- for(int i=1; i<=2020; i++){
- for(int j=i+1; j<=2021; j++){
- if(Math.abs(i-j)<=21){
- g[i].add(new int [] {j, f(i,j)}) ;
- g[j].add(new int [] {i, f(i,j)}) ;
- }
- }
- }
- int [] dist = new int [2022] ;
- for(int i=1; i<2022; i++){
- dist[i] = Integer.MAX_VALUE ;
- }
- dist[1] = 0 ;
-
- //优先队列,按权值进行升序排序
- PriorityQueue<int []> queue = new PriorityQueue<int[]>((a,b)->a[1]!=b[1] ? a[1] - b[1] : a[0] - b[0]) ;
- queue.add(new int[]{1,0}) ; //到达的节点和对应的权值
- while(!queue.isEmpty()){
- int [] p = queue.poll() ;
- int x = p[0], w = p[1] ;
- if(dist[x]<w){
- continue;
- }
- for(int [] edges : g[x]){
- int y = edges[0], d = dist[x] + edges[1] ;
- if(d<dist[y]){
- dist[y] = d ;
- queue.add(new int [] {y, d}) ;
- }
- }
- }
- System.out.println(dist[2021]);
-
-
- }
- private static int f(int a, int b){
- return a * b / gcd(a,b) ;
- }
- private static int gcd(int a, int b){
- if(b==0){
- return a ;
- }else{
- return gcd(b,a%b) ;
- }
- }
- }
答案:881012367360
思路:状压+dp,f[i][j]表示从1出发走到j且经过i得方案数,用二进制表示经过点的状态。
- public class Main {
- static boolean [][] edges ;
- static int m = 1 << 21 ;
- static long [][] f ;
- public static void main(String[] args) {
- edges = new boolean [21][21] ;
- f = new long [m][21] ;
- for(int i=1; i<=21; i++){
- for(int j=1; j<=21; j++){
- if(gcd(i,j)==1){
- edges[i-1][j-1] = true ;
- }
- }
- }
-
- f[1][0] = 1 ;
- for(int i=0; i<=m-1; i++){
- for(int j=0; j<=20; j++){
- if((i>>j & 1) != 0){
- for(int k=0; k<=20; k++){
- if((i-(1<<j)>>k & 1)!=0 && edges[k][j]){
- f[i][j] += f[i-(1<<j)][k] ;
- }
- }
- }
- }
- }
- long ans = 0 ;
- for(int i=1; i<=20; i++){
- ans += f[m-1][i] ;
- }
- System.out.println(ans);
-
- }
-
- private static int gcd(int m, int n) {
- if(n==0){
- return m ;
- }else{
- return gcd(n, m%n) ;
- }
- }
-
- }
思路:模拟,将总毫秒数对一天的毫秒数取余,得到的time是剩余需要操作的毫秒数,计算出时分秒即可,如果是个位数,需要在前面补零。
- import java.util.Scanner;
-
- public class Main {
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in) ;
- long t = input.nextLong() ;
-
- long ms = 24 * 60 * 60 * 1000 ;
- long time = t % ms ;
-
- long hour = time / 3600000 ;
- long min = (time % 3600000) / 60000 ;
- long sec = ((time%3600000) % 60000) / 1000 ;
-
- String h = String.valueOf(hour) ;
- String m = String.valueOf(min) ;
- String s = String.valueOf(sec) ;
- if(h.length()==1){
- h = "0" + h ;
- }
- if(m.length()==1){
- m = "0" + m ;
- }
- if(s.length()==1){
- s = "0" + s ;
- }
-
- System.out.println(h + ":" + m + ":" + s);
- }
- }
思路:规律题,我们想使用最少的砝码称出任意小于等于N的正整数数量,我们用count记录 砝码个数,weight记录所需的最后一个砝码的重量,total记录砝码能称出的总重量,这样会发现weight每次应该乘以3,而total等于上一轮的toal加上这次的weight。
- import java.util.Scanner;
-
- public class Main {
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in) ;
- int N = input.nextInt() ;
- int count = 1 ; //砝码个数
- int weight = 1 ; //最后一个砝码的重量
- int total = 1 ; //砝码能称出的总重量
-
- while(total<N){
- count ++ ;
- weight *= 3 ;
- total += weight ;
- }
-
- System.out.println(count);
-
- }
- }
思路:这题想AC,不太容易,很容易爆内存,那就先混分吧,开辟二维数组记录杨辉三角,然后转成一维数组,vis数组标记是否是第一次出现,index数组记录第一次出现的位置。
- import java.util.Scanner;
-
- public class Main {
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in) ;
- int N = input.nextInt() ;
- int [][] a = new int [20][20] ;
- int [] ans = new int [100000000] ;
- int [] vis = new int [100000000] ;
- int [] index = new int [100000000] ;
- for(int i=0; i<20; i++){
- for(int j=0; j<=i; j++){
- if(i==j || j==0){
- a[i][j] = 1 ;
- }else{
- a[i][j] = a[i-1][j-1] + a[i-1][j] ;
- }
- }
- }
-
- int k = 0 ;
- for(int i=0; i<20; i++) {
- for (int j = 0; j <= i; j++) {
- ans[k++] = a[i][j] ;
- if(vis[a[i][j]]==0){
- vis[a[i][j]] = 1 ;
- index[a[i][j]] = k ;
- }
- }
- }
- System.out.println(index[N]);
- }
- }
思路:这题考的是线段树,对于混分大师来说,根据题意模拟双向排序就行。
- import java.util.Arrays;
- import java.util.Scanner;
-
- public class Main {
- static int [] a ;
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in) ;
- int n = input.nextInt() ;
- int m = input.nextInt() ;
-
- a = new int [n] ;
-
- for(int i=1; i<=n; i++){
- a[i-1] = i ;
- }
-
- for(int i=1; i<=m; i++){
- int p = input.nextInt() ;
- int q = input.nextInt() ;
- if(p==0) {
- desc(a,0,q-1);
- }else if(p==1){
- asc(a,q-1,n-1) ;
- }
- }
- for(int i=0; i<a.length; i++){
- System.out.print(a[i]+" ");
- }
- }
-
- private static void desc(int[] a, int begin, int end) {
- int [] ans = new int [end-begin+1] ;
- int j = 0 ;
- for(int i=begin; i<=end; i++){
- ans[j++] = a[i] ;
- }
- Arrays.sort(ans);
- j-- ;
- for(int i=begin; i<=end; i++){
- a[i] = ans[j--] ;
- }
- }
-
- private static void asc(int[] a, int begin, int end) {
- int [] ans = new int [end-begin+1] ;
- int j = 0 ;
- for(int i=begin; i<=end; i++){
- ans[j++] = a[i] ;
- }
- Arrays.sort(ans);
- j = 0 ;
- for(int i=begin; i<=end; i++){
- a[i] = ans[j++] ;
- }
- }
- }
思路:有些难的动态规划了,思路可以参考这个:蓝桥杯 - 分果果 - SOSCHINA - 博客园
- import java.io.*;
- import java.util.*;
-
- public class Main {
-
- public static void main(String[] args) { new Main().run(); }
-
- int INF = 0x3F3F3F3F;
-
- void run() {
- InputReader in = new InputReader(System.in);
- int n = in.readInt(), m = in.readInt(), ans = INF;
- int[][][] dp = new int[m + 1][n + 1][n + 1];
- int[] S = new int[n + 1];
- for (int i = 1; i <= n; i++)
- S[i] = S[i - 1] + in.readInt();
- for (int i = 0; i <= m; i++)
- for (int j = 0; j <= n; j++)
- for (int k = 0; k <= j; k++) dp[i][j][k] = INF;
- dp[0][0][0] = 0;
- for (int min = S[n] * 2 / m; min > 0; min--) {
- for (int i = 1; i <= m; i++)
- for (int j = 1; j <= n; j++) {
- int trans2 = 0, trans3 = 0;
- for (int k = 1; k <= j; k++) {
- dp[i][j][k] = dp[i][j][k - 1];
- while (trans2 < k && S[j] - S[trans2 + 1] >= min &&
- max(dp[i - 1][trans2 + 1][trans2 + 1], S[j] - S[trans2 + 1]) <= max(dp[i - 1][trans2][trans2], S[j] - S[trans2])) trans2++;
- if (S[j] - S[trans2] >= min)
- dp[i][j][k] = min(dp[i][j][k], max(dp[i - 1][trans2][trans2], S[j] - S[trans2]));
- while (trans3 < k && S[j] - S[trans3 + 1] >= min &&
- max(dp[i - 1][k][trans3 + 1], S[j] - S[trans3 + 1]) <= max(dp[i - 1][k][trans3 + 1], S[j] - S[trans3])) trans3++;
- if (S[j] - S[trans3] >= min)
- dp[i][j][k] = min(dp[i][j][k], max(dp[i - 1][k][trans3], S[j] - S[trans3]));
- }
- }
- ans = min(ans, dp[m][n][n] - min);
- }
- System.out.println(ans);
- }
-
- int max(int arg1, int arg2) { return arg1 > arg2 ? arg1 : arg2; }
-
- int min(int arg1, int arg2) { return arg1 < arg2 ? arg1 : arg2; }
-
- class InputReader {
-
- BufferedReader reader;
- StringTokenizer token;
-
- InputReader(InputStream in) {
- this.reader = new BufferedReader(new InputStreamReader(in));
- }
-
- String read() {
- while (token == null || !token.hasMoreTokens()) {
- try {
- token = new StringTokenizer(reader.readLine());
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return token.nextToken();
- }
-
- int readInt() { return Integer.parseInt(read()); }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。