蓝桥第十三届JavaC组省赛回顾(A8题,H巧思满分)

A:排列字母

B:特殊时间

C:纸张尺寸

D:求和

E:矩形拼接

F:选数异或

G:GCD

H:青蛙过河

I:因数平方和

J:最长不下降子序列

A:排列字母

 日常签到题

import java.util.Arrays;

public class 字母排列 {
    public static void main(String[] args) {
        String ss="WHERETHEREISAWILLTHEREISAWAY";
        char []arr=new char[ss.length()];
        for (int i=0;i<ss.length();i++) {
            arr[i]=ss.charAt(i);
        }
        Arrays.sort(arr);
        for (int i=0;i<ss.length();i++)
            System.out.print(arr[i]);
    }
}

AAAEEEEEEHHHIIILLRRRSSTTWWWY

B:特殊时间

这题是 手推所有可能

答案:212 

C:纸张尺寸

大题的签到题,直接开数组存放每一种从尺寸即可

import java.util.Scanner;

public class 纸张尺寸 {
    public static void main(String[] args) {
        int [][]arr=new int[10][2];
        Scanner sc=new Scanner(System.in);
        int a=1189,b=841;
        arr[0][0]=1189;
        arr[0][1]=841;
        for (int i=1;i<10;i++){
            arr[i][0]=Math.min(a,b);
            if (a>b) {
                a /= 2;
            }
            else{
                b/=2;
            }
            arr[i][1]=Math.min(a,b);
        }
        String ss=sc.next();
        int t=ss.charAt(1)-'0';
        System.out.println(arr[t][0]);
        System.out.println(arr[t][1]);
    }
}

D:求和

S=a_{1}*(a_{1}+a_{2}+a_{3}+....+a_{n})+a_{2}*(a_{3}+a_{4}+ ....+a_{n})+....+a_{n-1}*a_{n}​​​​

我们设F(n)=a_{1}+a_{2}+a_{3}+.......+a_{n}​​

那么可得:S=a_{1}*(F(n)-f(1))+a_{2}*(F(n)-F(2))+.....+a_{n-1}*( F(n)-F(n-1))​​

因此,在写代码的时候,我们计算一下所有数的总和,每一次都是从其中去取出一个数即可

import java.util.Scanner;

public class 求和 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        long s=0;
        int n=sc.nextInt();
        int []arr=new int[n];
        for (int i=0;i<n;i++){
            arr[i]=sc.nextInt();
            s+=arr[i];//求和
        }
        long count=0;//求S值,long防爆
        for (int i=0;i<n;i++){
            count+=arr[i]*(s-arr[i]);
            s-=arr[i];//每一次取出一个数
        }
        System.out.println(count);
    }
}

E:矩形拼接

​​​​​​​​

这题 分类讨论,代码就不写了(十多个if)

​​它的三块拼接,边数只可能出现4/6/8这三种可能

F:选数异或

​​​​

因为小怂比较菜,水平有限,这题没A,有兴趣可以看一下肖佬的题解​​

G:GCD

​​​​​​​​​

 给定任意两数A和B(A<B)

那么它们之间的差值为B-A

​​​​​​​​​假设A,B存在非1的公因子​​​​​​​C

​​​​​​​​​即A%C=0&&B%C=0

​​​​​​​​​可得(B-A)%C=0

​​​​​​​​​那么,是否可得C的最大值为B-A?

​​​​​​​​​因此,当存在(A+k,B+k)的最大因子即为 (B-A)

​​​​​​​​所以,只需要构造(A+k)%(B-A)=0,且k尽可能小(k>0)

​​​​​​​​那么,我们可以求出A%(B-A)后,B-A减去该值,即为A最小增加k个值可以满足下一个模为0的值

​​​​​​​​​当然,还有另一个方案:C=A/(B-A),则k=(C+1)*(B-A)-A;

import java.util.Scanner;

public class GCD {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        long a=sc.nextLong();
        long b=sc.nextLong();
        long max=Math.abs(a-b);
        System.out.print(max-(a%max));
    }
}

H:青蛙过河

​​​​​​​​​

 这题先说说思路吧:

一开始我的思路是前缀和+后缀和

​​​​​​​​​因为在满足条件的同时,后面的格子中也要有可以停留的位置才能满足条件

​​​​​​​​​但是在写代码的时候遇到了困难

​​​​​​​​​然后群里人说:二分贪心可以做,又去试了一下,写不出来,因为是一个反复跳

​​​​​​​​​最后我思考出正确方案:前缀和+双指针

​​​​​​​​​我们从0位置开始,因为是来回跳2x次,我们先假设跳跃能力为A

​​​​​​​​​则每次可以跳:1,2...A格

那么前提条件就是:我要跳过去x​​​​​​​​​次,那么这A格是不是要有x个落脚点我才可以每一次跳过去的时候可以选择1--A格跳跃

​​​​​​​​​既然过去是x次,回来x次,那么这些格子是不是总共需要停留2x次

​​​​​​​​​即我需要满足条件:A格内的值和大于等于2x

​​​​​​​​​但是我要进行多次往前跳,所以我们需要让每一次跳完后,后面的A个格子内的值和都>=2x即可

​​​​​​​​​(可能讲的不是很清楚,瞅瞅代码,还不懂评论区回复)​​​​​​​

import java.util.Scanner;

public class 青蛙过河 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        long x=sc.nextLong();
        long []arr=new long[n+1];
        for (int i=1;i<n;i++){
            arr[i]=sc.nextLong()+arr[i-1];
        }
        arr[n]=arr[n-1]+9999999999L;
        int l=0;
        int sum=0;
        for (int i=1;i<=n;i++){
            if (arr[i]-arr[l]>= 2L *x){
                sum=Math.max(sum,i-l);
                l+=1;
            }
        }
        System.out.println(sum);
    }
}

I:因数平方和

这题用数论分块(不会分块的小伙伴可以百度一下,挺容易理解的)

我的思路:

先判断哪一部分的因数出现次数相同

比如:n=10

那么6/7/8/9/10这5个因子都只出现1次,而4/5则出现2次,3出现3次,2出现5次,1出现10次

然后用连续自然数平方和公式计算总值,乘出现的次数即可(数值过大,开大数)

但是,如果纯粹从1可是到n,那么结果依旧是O(n),会超时

所以在运算时,我们选择判断到一定值后从前往后计算每个数出现的次数

那么这个值我们一般定为\sqrt{n}

import java.math.BigInteger;
import java.util.Scanner;

public class 因数平方和 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int k= (int) Math.sqrt(n);
        int l=0;
        int r=n;
        long s=0;
        BigInteger a = BigInteger.valueOf(1), b = BigInteger.valueOf(2), c = BigInteger.valueOf(6),d,sum=BigInteger.valueOf(0);
        for (int i=1;i<=k;i++){
            l=n/(i+1);
            BigInteger x = BigInteger.valueOf(r), y = BigInteger.valueOf(l);
            d=BigInteger.valueOf(i);
            x = x.multiply(x.add(a)).multiply(x.multiply(b).add(a)).divide(c);
            y = y.multiply(y.add(a)).multiply(y.multiply(b).add(a)).divide(c);
            x = d.multiply(x.subtract(y)).mod(BigInteger.valueOf(1000000007));
            sum=(sum.add(x)).mod(BigInteger.valueOf(1000000007));
            r=l;
        }
        for (int i=1;i<=l;i++){
            k = n / i;
            s += (k * ((long) i * i)) % 1000000007;
            s %= 1000000007;
        }
        sum=(sum.add(BigInteger.valueOf(s))).mod(BigInteger.valueOf(1000000007));
        System.out.println(sum);
    }
}

J:最长不下降

 ​

因为小怂比较菜,水平有限,这题没A,有兴趣可以看一下肖佬的题解​​

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值