zoukankan      html  css  js  c++  java
  • 魔法排列

    题目

    题目连接:魔法排列

    众所周知,集合 {1 2 3 … N} 有 N! 种不同的排列,假设第 i 个排列为 Pi 且 P[i][j] 是该排列的第 j 个数。

    将 N 个点放置在 x 轴上,第 i 个点的坐标为 xi 且所有点的坐标两两不同。

    对于每个排列(以 Pi 为例),可以将其视为对上述 N 个点的一种遍历顺序,即从第 P[i][1] 个点出发,沿直线距离到达第 P[i][2] 个点,再沿直线距离到达第 P[i][3] 个点,以此类推,最后到达第 P[i][N] 个点,将该路线的总长度定义为 L(Pi),那么所有 N! 种路线的总长度之和是多少,即 L(P1) + L(P2) + L(P3) + ... + L(PN!) 的结果是多少?

    输入描述

    第一行包含一个整数 N,1 ≤ N ≤ 10^5。
    第二行包含 N 个空格隔开的整数 x1 到 xN,0 ≤ x1 < x2 < x3 < ... < xN ≤ 10^9。

    输出描述

    输出 L(P1) + L(P2) + L(P3) + ... + L(PN!) 对 10^9 + 7 取模后的结果。

    样例输入

    3
    0 1 3

    样例输出

    24

    说明

    P1={1 2 3},P2={1 3 2},P3={2 1 3},P4={2 3 1},P5={3 1 2},P6={3 2 1};
    L(P1)=3,L(P2)=5,L(P3)=4,L(P4)=5,L(P5)=4,L(P6)=3。

    AC 代码

    import java.util.Scanner;
    
    /**
     * 思路:这道题的主要思路是排列组合
     *
     *      例如有4个数[1, 2, 3, 4],那么所有的排列组合为:
     *      1 2 3 4 --- 1 2 4 3 --- 1 3 2 4 --- 1 3 4 2 --- 1 4 2 3 --- 1 4 3 2
     *      2 1 3 4 --- 2 1 4 3 --- 2 3 1 4 --- 2 3 4 1 --- 2 4 1 3 --- 2 4 3 1
     *      3 1 2 4 --- 3 1 4 2 --- 3 2 1 4 --- 3 2 4 1 --- 3 4 1 2 --- 3 4 2 1
     *      4 1 2 3 --- 4 1 3 2 --- 4 2 1 3 --- 4 2 3 1 --- 4 3 1 2 --- 4 3 2 1
     *
     *      可以发现,任意连个数相邻的情况都为 6,例如有 6 个 1 2
     *      这个 6 是怎么来的呢?可以把 1 2 捆绑在一起,那么就变成了如何将 1 2 3 4 放在三个坑中
     *      得到 A(3, 3) = 6 种
     *
     *      其他的方式也一样,另外 1 2 和 2 1 是两种不同的组合,在计算时只需要乘以 2 即可
     */
    public class Test {
    
        public static long mod = 1000000007;
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int N = scanner.nextInt();
            int[] x = new int[N];
            for (int i = 0; i < N; i++) {
                x[i] = scanner.nextInt();
            }
            int n = factorial(x.length - 1);
    
            /**
             * 时间复杂度 O(N)
             *
             * 思想:
             *      例如 1 2 3 4 要计算 len(1, 4) + len(2, 4) + len(3, 4)
             *      = (4 - 1) + (4 - 2) + (4 - 3)
             *      = 4 * 3 - (1 + 2 + 3)
             */
            long sum = 0, tem = 0, a;
            for (int i = 1; i < x.length; i++) {
                tem = (tem + x[i - 1]) % mod;
                // 这里不能直接写成 a = x[i] * i;
                // 因为 a 的类型为 long,而 x[i] 和 i 都是 int 类型
                // 两个 int 类型的数相乘就有导致溢出
                a = x[i] * (long)i;
                sum = (sum + a - tem) % mod;
            }
            sum = (sum << 1) % mod;
            sum = (sum * n) % mod;
            System.out.println(sum);
        }
    
        // 计算 N!
        public static int factorial (int n) {
            long result = 1;
            for (int i = 1; i <= n; i++) {
                /**
                 * 这里可以这样计算的原因是
                 *      (a * b) % c = ((a % c) * (b % c)) % c
                 */
                result = (result * i) % mod;
            }
            return (int) result;
        }
    }
    
  • 相关阅读:
    Tomcat的SessionID引起的Session Fixation和Session Hijacking问题
    别把项目成功当目标!——项目经理的误区(1)(转)
    技术,项目经理的命?——项目经理的误区(3)(转)
    项目管理中,最难管的是什么?(转)
    项目经理的超越(三)人际优先,做事上的超越(转)
    大丈夫不可一日无权啊!——项目经理的误区(2)(转)
    舌尖上的职场(二)一起去吃饭吧!(转)
    舌尖上的职场(一)你最近还好吗?(转)
    【项目经理之修炼(10)】《初级篇》人际关系问题也是可以避免的(转)
    gcc与g++区别
  • 原文地址:https://www.cnblogs.com/debugxw/p/11410491.html
Copyright © 2011-2022 走看看