第十三届蓝桥杯省赛JavaA组解析

public class Main{
    public static void main(String[] args){
        System.out.println(4+(20-1)+20*(22-1));
}

答案:443

 方法一:蛮力算法,注意Long.MAX_VALUE为:9223372036854775807,闲着没事干儿可以用这个方法,答案约等于2e15<9e18(Long的最大值),可以循环出结果

public class Main {

    public static void main(String[] args) {
        long m=Long.MAX_VALUE;
        for(long i=0;i<m;i++) {
                if(
                        i%2==1&&
                        i%3==1&&
                        i%4==1&&
                        i%5==1&&
                        i%6==1&&
                        i%7==1&&
                        i%8==1&&
                        //此处省略
                        i%48==41&&
                        i%49==46
                        ) {
                    System.out.println(i);
                }else {
                    System.out.println("没有找到");
                }
        }
    }
}
 

方法二:利用步长逐步累加

public class Main{
    
    public static void main(String[] args) {   
        int[] a = {
                0, 0,//为了使a[i]与i匹配,这里放入0填充a[0],a[1]
                1, 2, 1, 4, 5, 4, 1, 2, 9, 0, 5, 10,
                11, 14, 9, 0, 11, 18, 9, 11, 11, 15, 17, 9,
                23, 20, 25, 16, 29, 27, 25, 11, 17, 4, 29, 22,
                37, 23, 9, 1, 11, 11, 33, 29, 15, 5, 41, 46
                };
        long begin = 1;//满足题给条件的第一个模2的情况,即模2等于1的情况
        long step = 1;
        for (int i = 2; i < a.length - 1; i++) {
            step = lcm(step, i);//每个步长本质就是前面i-1个数(除数)的最小公倍数
            while (begin% (i + 1) != a[i + 1]) {
                begin += step;//步长的作用就是为满足下一次模运算而逐步累加到目标值
            }
        }
        System.out.println(begin);
    }

    //求最大公约数,不用考虑a,b的大小关系,可以自动调整
    private static long gcd(long a, long b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    //求最小公倍数
    private static long lcm(long a, long b) {
        return (a * b)/ gcd(a, b) ;
    }
}
答案:2022040920220409

import java.util.Scanner;

public class Mian {

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int a[]=new int[n];
        for(int i=0;i<a.length;i++) {
            a[i]=sc.nextInt();
        }
        long s = 0;
        for(int i=0;i<a.length;i++) {
            for(int j=i+1;j<a.length;j++) {
                s+=a[i]*a[j];
            }
        }
        System.out.print(s);
    }

}

样例答案:117

 法一:

public class Main{

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int a=sc.nextInt();
        int b=sc.nextInt(),m;
        m=Math.abs(a-b);        /*假设m可被a+k,b+k整除,那么a%m=b%m,则(a-b)%m=0,要使得m最大,只需要令a-b的绝对值等于m即可。*/
        System.out.print((m-a%m)%m);        /*因为(a+k)%m=0,则a%m(或b%m)得到一个余数,而k值就是m-a%d,k值要保证最小,那么用k%m即可得到结果。*/
    }
}

法二:

令m=|a-b|,m就是a,b的最大公约数或者是最大公约数的最大倍数,即m确定了公约数的上限,m的大小位置有两个,一个是m在(a,b)之间,另一个是m比a和b都小。

第一种情况下,k值就是m-min(a,b)

第二种情况下,找到一个最小整数n,使得m*n>a,则k=m*n-a;或者找到一个最小整数n,使得m*n>b,则k=m*n-b

import java.util.*;
public class Main {
    public static void main(String args[]){
        Scanner in=new Scanner(System.in);
        long a,b;
        long m;
        a=in.nextLong();
        b=in.nextLong();
        m=Math.abs(a-b);
        long k=0;
        if(a==m||b==m) k=0;
        else if(m<=a&&m<=b) {
            long temp;
            long t;
           t=Math.max(a,b)/m+1;
           k=t*m-Math.max(a, b);
        }
        else {
            k=m-Math.min(a, b);
        }
        System.out.println(k);
    }
}

 参见:(12条消息) 第十三届蓝桥杯【蜂巢】最简单的解法_Wuxy1999的博客-CSDN博客

 

 import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
             Scanner sc = new Scanner(System.in);
             int n= sc.nextInt();
             long num=1;             
             long sum=1;
             long []dp=new long[n+1];
             dp[0]=0;
             dp[1]=0;
             for (int i = 2; i <=n ; i++) {
                 dp[i]=(dp[i-1]*(i)+num*sum)%998244353;
                 sum=(sum+i)%998244353;
                 num=(num*i)%998244353;
             }
             System.out.println(dp[n]);
    }
}

此处用到动态规划,数值n的全排列的价值可分为两部分,一部分是dp[n-1]*n,另外一部分是(n-1)!*(1+2+...+n-1)。

第一部分,dp[n-1]的价值假定已经确定,那么插入第n个数字的时候,每一个原排列会新产生n个新排列,那么全部新排列的价值就是dp[n-1]*n。例如,dp[4-1]的价值已经确定是9,那么插入第4个数字(也就是4),第一个原排列123会产生4123,1423,1243,1234四个新排列,而原排列一共有3!个,那么新的排列总共就有24个,但这24个排列在不考虑数字4引起的价值变化的前提下,全排列价值仅发生倍数变化,就是dp[3]*4,价值变化的原因也仅仅是排列数量的增多而已。

第二部分,我们的第一部分已经考虑了插入第n个数字后,排列增多引起的价值变化,但我们没有考虑第n个数字引起的价值变化。n-1个数字的排列有(n-1)!个,而对于每个排列,排列的间隔不会改变,数字n的插入位置有n种选择,插入数字n后,n的前面有几个数字,那么这个排列因为n的价值就是几(n在这个排列里面最大)。例如排列123,插入4,就有4123,1423,1243,1234,价值分别为0,1,2,3。所以,插入n引起的价值变化有(n-1)!*(1+2+...+n-1)。

 

法一:此方法思路简单,但已经超时

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        long x=0;
        int n;
        Scanner s=new Scanner(System.in);
        n=s.nextInt();
        for(int i=1;i<n+1;i++) {
            x+=f(i);
        }
        System.out.print(x%(1e9+7));
    }
    private static long f(long x) {
        long a=0;
        for(long i=1;i<x+1;i++) {
            if(x%i==0)a+=i*i;
        }
        return a;        
    }
}

法二:仅适用问题规模较小时,摘自https://blog.csdn.net/qq_46311811/article/details/124067689

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.close();

        long[] arr = new long[n + 1];
        long sum = 0;
        for (long i = 1; i < arr.length; i++) {
            long j = i;
            while (j < arr.length) {
                arr[(int) j] = (arr[(int) j] + i * i) % 1000000007;
                j += i;
            }
            sum = (sum + arr[(int) i]) % 1000000007;
        }

        System.out.println(sum);
    }
}
法三:最优算法,摘自https://blog.csdn.net/feng8403000/article/details/128891276

import java.util.Scanner;
public class Main{
    public static void main(String[] args) {
        final long N = 1000000007;
        final long inv6 = 166666668;
        Scanner sc = new Scanner(System.in);
        long res = 0, temp = 0, sum = 0;
        long n, l, r, k;
        n = sc.nextInt();
        sc.close();
        for (long i = 1; i <= n; i = r + 1) {
            l = i;
            k = n / i;
            r = n / (n / l);
            temp = sum;
            sum = r * (r + (long) 1) % N * ((long) 2 * r + 1) % N * inv6 % N;
            res = (res + k * (sum - temp) + N) % N;
        }
        System.out.println(res);
    }
}

 

import java.util.Arrays;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n,k ;
        n = sc.nextInt();
        k = sc.nextInt();
        int a[]= new int[n];
        for(int i=0;i<a.length;i++) {
            a[i] = sc.nextInt();
        }
        //Arrays.sort(a);
        System.out.println(f(a,k));        
    }
    private static  long f(int b[], int k) {
        int count = 0;//用于计数    
        int location = 0;//用于标记在数组中的位置
        while(location <= b.length -k) {//按步长k移动到最后b.length%k时,可以退出循环
            long min = Integer.MAX_VALUE;
            int c = 0;
            for(int i=location ;i<location+k;i++){//在步长k内进行循环,找到最小值
                if(b[i] <= min) {
                    min = b[i];
                    c = i;//假定序列已经按升序进行排列
                }
            }
            for(int i=location;i<location+k;i++) {
                b[i]-=min;//这里的min就是连续k个数统一减小的次数
            }
            count+=min;
            location=c+1;//记录下一次起始位置
        }        
        for(int j=location;j<b.length;j++) {//此时只能一个数一次一次的减小
            count+=b[j];
        }
        return count;
    }    
}

摘录自2022年蓝桥杯省赛java A组考后总结_java蓝桥杯a组_Hydrion-Qlz的博客-CSDN博客

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class Main{
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer in = new StreamTokenizer(bf);

    static int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    public static void main(String[] args) throws IOException {
        int N = nextInt();
        int M = nextInt();
        int Q = nextInt();
        int[][] knowArr = new int[N][N];
        int[][] givenArr = new int[M][2];
        for (int i = 0; i < givenArr.length; i++) {
            int l = nextInt() - 1;
            int r = nextInt() - 1;
            int S = nextInt();
            knowArr[l][r] = S;
            // 以l为终点
            if (l > 0) {
                for (int j = 0; j < N && j < l; j++) {
                    if (knowArr[j][l - 1] != 0) {
                        knowArr[j][r] = knowArr[j][l - 1] + S;
                    }
                }
            }
            // 以l为起点
            if (l < N - 1) {
                for (int j = l + 1; j < N; j++) {
                    if (knowArr[l][j] != 0) {
                        if (j < r) {
                            knowArr[j + 1][r] = S - knowArr[l][j];
                        } else if (j > r) {
                            knowArr[r + 1][j] = knowArr[l][j] - S;
                        }
                    }
                }
            }
            // 以r为终点
            if (r > 0) {
                for (int j = 0; j < N && j < r; j++) {
                    if (knowArr[j][r] != 0) {
                        if (j < l) {
                            knowArr[j][l - 1] = knowArr[j][r] - S;
                        } else if (j > l) {
                            knowArr[l][j - 1] = S - knowArr[j][r];
                        }
                    }
                }
            }
            // 以r为起点
            if (r < N - 1) {
                for (int j = r + 1; j < N; j++) {
                    if (knowArr[r][j] != 0) {
                        knowArr[l][j] = S + knowArr[r][j];
                    }
                }
            }
        }

        for (int i = 0; i < Q; i++) {
            int l = nextInt() - 1;
            int r = nextInt() - 1;
            if (knowArr[l][r] != 0) {
                System.out.println(knowArr[l][r]);
            } else {
                System.out.println("UNKNOWN");
            }
        }
    }
}

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值