一、内容

[Java] 计蒜客---蒜头君的玩具_i++

二、思路

  • 用差分数组算出每个点总共被包含了几次,比如1-4就等于1-4区间的数组都加上1。这样a数组最终保存的就是装了这个点总共被覆盖几次。
  • 由于每次只能选3条线段,所以数组里面每个点的值必须>=3才符合要求,要后从求一个c3a[i], a[i]表示这个点覆盖的次数,从里面能选出3条线段覆盖的种数。
  • 对所有点都求一次组合数,然后所有的组合数相加 / c3m 就是结果了。由于可能不能整除,所以还要求一次gcd。
    -note: 当m <= 2 时,直接输出0,因为都不满足。

三、代码

import java.io.PrintWriter;
import java.util.Scanner;

public class M_蒜头君的玩具 {
	static int[] a = new int[50005];
	static int[] d = new int[50005];
	static int n, m, l, r;
	static long x, y;
	static PrintWriter out = new PrintWriter(System.out);
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		for (int i = 1; i <= m; i++) {
			 l = sc.nextInt();
			 r = sc.nextInt();
			 d[l] += 1;
			 d[r + 1] -= 1;
		}
		for (int i = 1; i <= n; i++) {
			a[i] = d[i] + a[i - 1];
			if (a[i] >= 3) {
				x += c(a[i]);
			}
		}
		y = c(m);
		if (x == 0 || m <= 2) {
			out.println(0);
		} else {
			long gcd = gcd(x, y);
			x /= gcd;
			y /= gcd;
			if (x % y == 0) {
				out.println(x / y);
			} else {
				out.println(x + "/" + y);
			}
		}	out.close();
	}
	
	static long gcd(long a, long b) {
		if (b == 0) return a;
		return gcd(b, a % b);
	}
	
 	static long c(long m) {
		return m * (m - 1) * (m - 2) / 6;
	}
}