蓝桥杯--数学知识的运用(一) - Go语言中文社区

蓝桥杯--数学知识的运用(一)


数学知识的运用
1)并非数学竞赛
2)进制问题及其巧妙运用
3)整数与整除问题
4)欧几里得扩展定理
5)有理数表示,大数问题

例1【奇怪的捐赠】

地产大亨Q先生临终的遗愿是:拿出100万元给X社区的居民抽奖,以稍慰藉心中愧疚。
麻烦的是,他有个很奇怪的要求:
1. 100万元必须被正好分成若干份(不能剩余)。
  每份必须是7的若干次方元。
  比如:1元, 7元,49元,343元,...
  
2. 相同金额的份数不能超过5份。

3. 在满足上述要求的情况下,分成的份数越多越好!

请你帮忙计算一下,最多可以分为多少份?
  public static void main(String[] args) {
        //进制问题,将十进制转换为七进制
        String s = Integer.toString(100*100,7);
        System.out.println(s);//41104
         int sum = 0;
         for(int i = 0;i < s.length();i++){
             sum+=s.charAt(i)-'0';
         }
        System.out.println(sum);//10
    }
}

例2【天平称重】 

用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量。
如果只有5个砝码,重量分别是1,3,9,27,81
则它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中)。

本题目要求编程实现:对用户给定的重量,给出砝码组合方案。
例如:
用户输入:
5
程序输出:
9-3-1
用户输入:
19
程序输出:
27-9+1

要求程序输出的组合总是大数在前小数在后。
可以假设用户的输入的数字符合范围1~121。方法一(递归法):当x>权重/2时,需要动用大一点的数来减去
public class Main {
   
    public static String f(int x){
        int a = 1;
        while(a<x)
            a = a*3;
        if(a == x) return ""+x;
        //用前一级来+
        else if (x <= a/2) return a/3 + "+" + f(x-a/3);
        else return a + "-" + reverse(f(a-x));
    }
    //正负变号
    public static String reverse(String s){
        s = s.replace('+','#');
        s = s.replace('-','+');
        s = s.replace('#','-');
        return  s;
    }

    public static void main(String[] args) {
        for(int i=1;i<50;i++){
           System.out.println(i+":"+f(i));
        }

    }
}

方法二(进制法):

//天平称重,进制解法
public class Main {
    public static String f(int x){
        String s = "";
        int a = 1;//权重
        while(x > 0){
        int sh = x / 3;//商
            if(x%3 == 1){
                s = "+" + a + s;
            }
            else if(x%3 == 2){
                s = "-" + a + s;
                sh++;
            }
            a = a*3;
            x = sh;
        }
        return s.substring(1);
    }

    public static void main(String[] args) {
        for(int i=1;i<50;i++){
            System.out.println(i+":"+f(i));
        }
    }
}

例3【Excel地址】

Excel单元格的地址表示很有趣,它使用字母来表示列号,比如:
A表示第1列,
B表示第2列,
Z表示第26列,
AA表示第27列,
AB表示第28列,
BA表示第53列,
....
当然Excel的最大列号是有限度的,所以转换起来不难。
如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?

本题目既是要求对输入的数字, 输出其对应的Excel地址表示方式。

例如,
输入:
26
则程序应该输出:
Z

再例如,
输入:
2054
则程序应该输出:
BZZ

我们约定,输入的整数范围[1,2147483647]

解析:该题并不属于26进制类型,A是从1开始而不是从0开始,正确方式应该是利用暴力破解的逆向思维

例4【日期问题】

问题描述
  已知2011年11月11日是星期五,问YYYY年MM月DD日是星期几?注意考虑闰年的情况。尤其是逢百年不闰,逢400年闰的情况。
输入格式
  输入只有一行
  YYYY MM DD
输出格式
  输出只有一行
  W
数据规模和约定
  1599 <= YYYY <= 2999
  1 <= MM <= 12
  1 <= DD <= 31,且确保测试样例中YYYY年MM月DD日是一个合理日期
  1 <= W <= 7,分别代表周一到周日
样例输入
2011 11 11
样例输出
5

解析:A-B = A - 基准 - (B - 基准)

public class Main {

    public static void main(String[] args) {
        int w=5;
        Scanner sc=new Scanner(System.in);
        String []data=new String[3];
        data=sc.nextLine().split(" ");
        int year=Integer.parseInt(data[0]);
        int month=Integer.parseInt(data[1]);
        int date=Integer.parseInt(data[2]);
        int x=f(year,month,date)-f(2011,11,11);
        switch(x%7) {
            case 0:w=5;break;
            case 1:w=6;break;
            case 2:w=7;break;
            case 3:w=1;break;
            case 4:w=2;break;
            case 5:w=3;break;
            case 6:w=4;break;
            case -1:w=4;break;
            case -2:w=3;break;
            case -3:w=2;break;
            case -4:w=1;break;
            case -5:w=7;break;
            case -6:w=6;break;
        }
        System.out.println(w);
    }
    static Boolean is_leap_year(int n) {
        if((n%4==0&&n%100!=0)||n%400==0)
            return true;
        return false;
    }
    static int f(int year, int month, int date) {
        int [] m = {0,31,28,31,30,31,30,31,31,30,31,30,31};//易错 :月份从一开始,前面0不可省
        if(is_leap_year(year))
            m[2]++;//易错
        int sum=0;
        for(int i=1599;i<year;i++) {
            sum+=365;
            if(is_leap_year(i))
                sum=sum+1;
        }
        for(int i=1;i<month;i++) {
            sum+=m[i];
        }
        sum=sum+date;
        return sum;
    }
}

例5【模m运算】

有3堆硬币,分别是3,4,5
二人轮流取硬币。
每人每次只能从某一堆上取任意数量。
不能弃权。
取到最后一枚硬币的为赢家。
求先取硬币一方有无必胜的招法。 

解析:模2的加法(同余理论):1+1=0, 1+0=1, 0+1=1, 0+0=0
     理论:如果和为0,无论怎么拿,都会!=0;如果非0,总有办法...0 

若将局面变成1 4 5,模2加为0,那么留给对方的必为输局

//尼姆堆的模2加(异或)解法
public class Main {
    static void f(int []a){
        int sum = 0;
        for(int i=0;i<a.length;i++){
            sum^=a[i];
        }
        if(sum==0) {
            System.out.println("输局");
            return;
        }
        //x ^ y ^y = x
        for(int i=0;i<a.length;i++){
            int x = sum ^a[i];
            if(x < a[i])//拿了之后数量一定比之前少!!!
                System.out.println(a[i] + "-->" + x);
                /*  5-->0
                    12-->9
                    14-->11*/
        }
    }

    public static void main(String[] args) {
        int [] a = {2,5,12,14};
        f(a);
    }
}

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/Nibaby9/article/details/79739001
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-09-01 10:51:10
  • 阅读 ( 1062 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢