分糖果

/**
 * @author Wcy
 * @Date 2022/3/28 17:23
 */

import java.util.Arrays;
import java.util.Scanner;

/**
 有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
 每个小朋友都把自己的糖果分一半给左手边的孩子。
 一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
 反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
 你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。
 【格式要求】
 程序首先读入一个整数N(2<N<100),表示小朋友的人数。
 接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
 要求程序输出一个整数,表示老师需要补发的糖果数。
 例如:输入
 3
 2 2 4
 程序应该输出:
 4

 资源约定:
 峰值内存消耗(含虚拟机) < 256M
 CPU消耗  < 1000ms

 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
 注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
 注意:主类的名字必须是:Main,否则按无效代码处理。
 */
public class 分糖果 {
    public static void main(String[] args) {
        int add=0;
        Scanner scanner = new Scanner(System.in);
        int people=scanner.nextInt();
        int[] num=new int[people];
        for(int i=0;i<people;i++)
            num[i]= scanner.nextInt();
        while(true){
           int fir=num[0]/2;
           for(int i=0;i<num.length-1;i++){
               num[i]=num[i]/2+num[i+1]/2;
           }
           num[num.length-1]=num[num.length-1]/2+fir;
           //2 2 4     2 3 3
//           System.out.println(Arrays.toString(num));
           for(int i=0;i<num.length;i++)
               if(num[i]%2!=0) {
                   add++;
                   num[i]=num[i]+1;
               }
//            System.out.println(Arrays.toString(num));
            boolean judge=true;
            for(int i=0;i<num.length-1;i++)
                if(num[i]!=num[i+1]){
                    judge=false;
                }
            if(judge)
            {
                System.out.println(add);
                break;
            }

        }
    }
}

切面条

/**
 * @author Wcy
 * @Date 2022/3/28 15:20
 */

/**
 *   一根高筋拉面,中间切一刀,可以得到2根面条。
 *
 *     如果先对折1次,中间切一刀,可以得到3根面条。
 *
 *     如果连续对折2次,中间切一刀,可以得到5根面条。
 *
 *     那么,连续对折10次,中间切一刀,会得到多少面条呢?
 *
 * 答案是个整数,请通过浏览器提交答案。不要填写任何多余的内容。
 *
 */
public class 切面条 {
    /**
     * n-1:对折次数
     * 解析 1=1/2+2^(n-1)*(1/2^n)
     * n=1时:1=1/2+1/2
     * n=2时:1=1/2+1/4+1/4
     * n=3时:1=1/2+1/8+1/8+1/8+1/8
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(1+1024);
    }
}

圆周率

/**
 * @author Wcy
 * @Date 2022/3/28 15:52
 */

/**
 *   数学发展历史上,圆周率的计算曾有许多有趣甚至是传奇的故事。其中许多方法都涉及无穷级数。
 *
 *     图1.png中所示,就是一种用连分数的形式表示的圆周率求法。
 *
 *     下面的程序实现了该求解方法。实际上数列的收敛对x的初始值 并不敏感。
 *
 *     结果打印出圆周率近似值(保留小数点后4位,并不一定与圆周率真值吻合)。
 *
 *
 *     4/pai=1+x
 *
 *     double x = 111;
 *     for(int n = 10000; n>=0; n--){
 *         int i = 2 * n + 1;
 *         x = 2 + (i*i / x);
 *     }
 *
 *
 *
 *     System.out.println(String.format("%.4f", ______________));
 */

public class 圆周率 {
    public static void main(String[] args) {
        double x = 111;
        for(int n = 10000; n>=0; n--){
            int i = 2 * n + 1;
            x = 2 + (i*i / x);
        }

        System.out.println(String.format("%.4f", 4/(x-1)));
    }
}

地宫取宝

/**
 * @author Wcy
 * @Date 2022/3/28 17:44
 */

import java.util.Scanner;

/**
 *    X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
 *     地宫的入口在左上角,出口在右下角。
 *     小明被带到地宫的入口,国王要求他只能向右或向下行走。
 *     走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
 *     当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
 *     请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
 * 【数据格式】
 *     输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
 *     接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
 *     要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。
 * 例如,输入:
 * 2 2 2
 * 1 2
 * 2 1
 * 程序应该输出:
 * 2
 *
 * 再例如,输入:
 * 2 3 2
 * 1 2 3
 * 2 1 5
 * 程序应该输出:
 * 14
 *
 * 资源约定:
 * 峰值内存消耗(含虚拟机) < 256M
 * CPU消耗  < 2000ms
 *
 * 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
 *
 * 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
 * 注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
 * 注意:主类的名字必须是:Main,否则按无效代码处理。
 */
public class 地宫取宝 {

    private static long N = 1000000007;
    private static int n,m,k;
    private static int map[][] = new int[50][50];  //记录迷宫
    //dp中,四个参数各代表坐标X,Y、手中持有宝物数量、手中宝物的最大值 表示的是该状态到终点有多少条路径
    private static int dp[][][][] = new int[50][50][15][15];

    public static void init(){//初始化每个状态都是-1 所以-1就说明这个状态之后的路径没有计算过
        for(int i=0;i<50;i++){
            for(int j=0;j<50;j++){
                for(int k=0;k<15;k++){
                    for(int l=0;l<15;l++)
                        dp[i][j][k][l] = -1;
                }
            }
        }
    }

    /*
    就是一个搜索的函数,来不断地搜索,每次搜索到底的时候,
    也就是最后一个点的时候,虽然x、y是一样的,但是num和max也就是状态是不一样的
    但是显然我们知道最后一个点不论是什么状态它到终点的路径也只有一条
    所以会return一个1 然后回到递归的上一层 也就是上一个点的状态 可能它是往右到达最后这个点的
    还是往下到达这个点的 它 也就是调用了这个return 1 的这次dfs的那个点的状态 它的s必须要加上这个1
    然后一层一层往上递推 s是不断地增加的 直到初始点 的初始状态 它的dp值 也就是s 就是我们所要的答案
     */
    public static int DFS(int x, int y, int num, int max){
        //首先函数的前面可以写一些代码来控制条件来剪枝 减少一些无用的搜索
        //记忆化搜索,首先先检查该路径是否已经走过
        if(dp[x][y][num][max+1]!=-1){
            //说明已经走过这个条路径,就不用再次走(这个状态之前已经到过了,所以不用再计算了,直接返回之前得出的该状态的数值)
            //因为宝物有可能为0所以定义max时用最小值-1 这就导致无法作为下标使用
            //实际上如果测试数据中宝物价值没有0,将所有的+1 去掉也是可以的
            return  dp[x][y][num][max+1];
        }

        //到达边界
        if(x==n-1 && y==m-1){
            /*到达下角有两种情况成功
             * 1.当前手中的数量正好等于题目所要的k,这时不拿会成功
             * 2.当前手中的数量刚好差一个,然后地下的宝物大于手中的max,这时也会成功
             */
            if(num==k || (num==k-1 && max<map[x][y])){
                return dp[x][y][num][map[x][y]]=1;  //这里返回的1就是上文所提到的 这个状态到终点有一条路径 然后往外层递推一直递推到初始状态就是答案
            }else{
                return dp[x][y][num][max+1]=0;      //不满足条件,这里的max+1原因同上
            }
        }

        /*拿和不拿的两种情况:
         * 1.手中的max大于地下宝物价值,此时可拿可不拿
         * 2.手中的max小于地下宝物价值,此时只能不拿
         */
        long s = 0;
        if(x<n-1){//向下搜索
            if(max<map[x][y]){//可拿可不拿,不拿的情况可以想成是不符合条件所以不拿,这样来说就可以将其和不能拿一起处理
                s += DFS(x+1, y, num+1, map[x][y]);
            }
            s += DFS(x+1, y, num, max);//不拿,与不能拿时写在一起,这点很重要!
            s%=N;
        }

        if(y<m-1){//向右搜索
            if(max<map[x][y]){//可拿可不拿,不拿的情况可以想成是不符合条件所以不拿,这样来说就可以将其和不能拿一起处理
                s += DFS(x, y+1, num+1, map[x][y]);
            }
            s += DFS(x, y+1, num, max);//不拿,与不能拿时写在一起,这点很重要!
            s%=N;
        }

        //说明本层内的都回溯完了 也就是本层dfs结束 此时要赋给这个状态s 即表示有多少条路径到达终点
        return  dp[x][y][num][max+1]=(int) s;

    }
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        m = scan.nextInt();
        k = scan.nextInt();
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                map[i][j] = scan.nextInt();
            }
        }
        init();
        DFS(0, 0, 0, -1);
        System.out.println(dp[0][0][0][0]);//起点刚开始什么都没有的状态 这个状态的值就是答案
    }
}

大衍数列

/**
 * @author Wcy
 * @Date 2022/3/28 15:50
 */

/**
 * 中国古代文献中,曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。
 * <p>
 * 它的前几项是:0、2、4、8、12、18、24、32、40、50 ...
 * <p>
 * 其规律是:对偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。
 * <p>
 * 以下的代码打印出了大衍数列的前 100 项。
 * <p>
 * for(int i=1; i<100; i++)
 * {
 * if(________________)  //填空
 * System.out.println(i*i/2);
 * else
 * System.out.println((i*i-1)/2);
 * }
 * 请填写划线部分缺失的代码。通过浏览器提交答案。
 * <p>
 * 注意:不要填写题面已有的内容,也不要填写任何说明、解释文字。
 * <p>
 * i%2==0
 */
public class 大衍数列 {
    public static void main(String[] args) {
        for (int i = 1; i < 100; i++) {
            if (i % 2 == 0)  //填空
                System.out.println(i * i / 2);
            else
                System.out.println((i * i - 1) / 2);
        }
    }
}

奇怪的分式

/**
 * @author Wcy
 * @Date 2022/3/28 15:57
 */

/**
 *  上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:
 *
 *     1/4 乘以 8/5
 *
 *     小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png)
 *
 *     老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!
 *
 *     对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢?
 *
 *     请写出所有不同算式的个数(包括题中举例的)。
 *
 *     显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。
 *
 *     但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!
 *
 * 注意:答案是个整数(考虑对称性,肯定是偶数)。请通过浏览器提交。不要书写多余的内容。
 */
public class 奇怪的分式 {
    public static void main(String[] args) {
//        好家伙,相当暴力
        int ans=0;
        for(int a=1;a<10;a++)
            for(int b=1;b<10;b++)
                for(int c=1;c<10;c++)
                    for(int d=1;d<10;d++) {
                        int e = 10*a+c;
                        int f = 10*b+d;
                        if(a==b || c==d)
                            continue;
                        if(a*c*f==e*b*d) {
                            ans++;
                            System.out.println(a+"/"+b+" x "+c+"/"+d+" = "+e+"/"+f+"  "+ans);
                        }
                    }
    }

}

扑克序列

/**
 * @author Wcy
 * @Date 2022/3/28 15:59
 */

import java.util.Arrays;

/**
 * A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。
 * 要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。
 * <p>
 * 请填写出所有符合要求的排列中,字典序最小的那个。
 * <p>
 * 例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
 * <p>
 * <p>
 * 请通过浏览器提交答案。“A”一定不要用小写字母a,也不要用“1”代替。字符间一定不要留空格。
 */
//2342A3A4
public class 扑克序列 {
    // A比2大  所有A>=5
    public static String result = "AAAAAAAA";

    // 排列
    public static void f(char[] a, int k) {
        if (k == a.length - 1) {
            work(a);
            return;
        } else {
            for (int i = k; i < a.length; i++) {
                {
                    char t = a[k];
                    a[k] = a[i];
                    a[i] = t;
                }
                f(a, k + 1);
                {
                    char t = a[k];
                    a[k] = a[i];
                    a[i] = t;
                }
            }
        }
        return;
    }

    // 筛选符合题意的
    public static void work(char[] a) {
        char temp1 = 'A', temp2 = '2', temp3 = '3', temp4 = '4';
        int dA = distance(a, temp1);
        int d2 = distance(a, temp2);
        int d3 = distance(a, temp3);
        int d4 = distance(a, temp4);
        // 两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌
        if (dA == 1 && d2 == 2 && d3 == 3 && d4 == 4) {
            String A = "";
            for (int i = 0; i < a.length; i++) {
                A += a[i];
            }
            if (A.compareTo(result) < 0)
                result = A;
            return;
        }
    }

    // 计算相同字符之间的距离
    public static int distance(char[] a, char temp) {
        for (int i = 0; i < a.length; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (a[i] == temp && a[j] == temp) {
                    return j - (i + 1);
                }
            }
        }
        return 0;
    }

    public static void main(String[] args) {
        f("AA223344".toCharArray(), 0);
        System.out.println(result);
    }


}

武功秘籍

/**
 * @author Wcy
 * @Date 2022/3/28 15:16
 */

/**
 * 小明到X山洞探险,捡到一本有破损的武功秘籍(2000多页!当然是伪造的)。他注意到:书的第10页和第11页在同一张纸上,但第11页和第12页不在同一张纸上。
 * <p>
 * 小明只想练习该书的第81页到第92页的武功,又不想带着整本书。请问他至少要撕下多少张纸带走?
 * <p>
 * 这是个整数,请通过浏览器提交该数字,不要填写任何多余的内容。
 */
public class 武功秘籍 {
    //    偶数页在正面,奇数页在反面
    //此题无需代码
//    (80,81) +(82,83)+(84,85)+(86,87)+(88.89),(90,91) +(92,93)
    public static void main(String[] args) {
        System.out.println(7);
    }
}

猜字母

/**
 * @author Wcy
 * @Date 2022/3/28 15:28
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 把abcd...s共19个字母组成的序列重复拼接106次,得到长度为2014的串。
 * <p>
 * 接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字母。
 * <p>
 * 得到的新串再进行删除奇数位置字母的动作。如此下去,最后只剩下一个字母,请写出该字母。
 * <p>
 * 答案是一个小写字母,请通过浏览器提交答案。不要填写任何多余的内容。
 */
public class 猜字母 {
    public static void main(String[] args) {
        String[] str = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s"};

        List<String> strList = new ArrayList<>();
        for (int i = 0; i < 106; i++) {
            strList.addAll(Arrays.asList(str));
        }
        while (true) {
            for (int i = 0; i < strList.size(); i++) {
                if (i % 2 == 0)
                    strList.set(i, "");
            }
            //或者直接使用字符串的replace也可以 看个人喜好
            System.out.println(Arrays.toString(strList.toArray()));
            while(strList.contains("")) {
                strList.remove("");
            }
            if(strList.size()==1) {
                System.out.println(Arrays.toString(strList.toArray()));
                break;
            }
        }

    }
}

矩阵翻硬币

/**
 * @author Wcy
 * @Date 2022/3/28 17:54
 */

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

/**
 * 小明先把硬币摆成了一个 n 行 m 列的矩阵。
 *     随后,小明对每一个硬币分别进行一次 Q 操作。
 *     对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。
 *     其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。
 *     当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。
 *     小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。
 *     聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
 * 【数据格式】
 *     输入数据包含一行,两个正整数 n m,含义见题目描述。
 *     输出一个正整数,表示最开始有多少枚硬币是反面朝上的。
 * 【样例输入】
 * 2 3
 * 【样例输出】
 * 1
 * 【数据规模】
 * 对于10%的数据,n、m <= 10^3;
 * 对于20%的数据,n、m <= 10^7;
 * 对于40%的数据,n、m <= 10^15;
 * 对于10%的数据,n、m <= 10^1000(10的1000次方)。
 *
 * 资源约定:
 * 峰值内存消耗(含虚拟机) < 256M
 * CPU消耗  < 2000ms
 */

/**
 *
 //第x行第y列被翻动的总次数
 //考虑第1行,第y列,y有多少真因子,就会被翻动多少次,而所有的y中,只有平方数的真因子个数为奇数(约数总是成对出现的)
 //考虑第1列,第x行,x有多少真因子,就会被翻动多少次,而所有的x中,只有平方数的真因子个数为奇数
 //x,y硬币被翻动的次数=x真因子个数*y真因子个数,只有奇数*奇数=奇数,所以,若要x,y为反面,必须x,y都是平方数
 //因此,反面硬币总数=m中的平方数的个数*n中平方数的个数
 //那么在m中有多少个平方数呢?答案是sqrt(m)向下取整个,如9内有三个平方数1,4,9;16里面有4个平方数1,4,9,16;25内有5个平方数
 //因此此题等价于求sqrt(m)*sqrt(n),那么怎么对一个很大的数开平方呢?
 //假设一个数的长度为length,其平方根的长度为length/2(偶数)或者length/2+1(奇数)

 */
public class 矩阵翻硬币 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s1 = sc.next();
        String s2 = sc.next();
        System.out.println(sqrt(s1).multiply(sqrt(s2)));
    }

    private static BigInteger sqrt(String s) {
        int length = s.length();
        int len = 0;
        if (length % 2 == 0)
            len = length / 2;
        else
            len = length / 2 + 1;
        char[] sArr = new char[len];
        Arrays.fill(sArr, '0');
        BigInteger target = new BigInteger(s);
        for (int pos = 0; pos < len; pos++) {
            for (char c = '1'; c <= '9'; c++) {
                sArr[pos] = c;//在pos这个位置上试着填入1-9
                BigInteger pow = new BigInteger(String.valueOf(sArr)).pow(2);//平方
                if (pow.compareTo(target) > 0)//试探数的平方更大
                {
                    sArr[pos] -= 1;
                    break;
                }
            }
        }
        return new BigInteger(String.valueOf(sArr));
    }

}
最后修改:2022 年 03 月 30 日
如果觉得我的文章对你有用,请随意赞赏