Day008 洛谷 P2181 对角线

洛谷 P2181 对角线

题目


思路分析

  1. 任何三条对角线都不会交于一点,也就是说,每一个交点仅由两条线相交而得,一个交点对应两条对角线
  2. 每条对角线对应两个顶点,顶点的个数与多边形的边数相等
  3. 所以能得出交点与边数的关系,一个交点-->两条对角线-->四个顶点=四条边
  4. 所以”求交点的个数“可以转化成“求有多少种四个顶点的组合”
  5. 以六边形为例,从六个顶点中任选四个顶点,使用组合数公式可以得出,一共有(6*5*4*3)/(4*3*2*1)=15种。三边形由于凑不出四个顶点,所以没有交点,符合输出样例的结果

用代码写出来

C/C++

#include<bits/stdc++.h>
int main(){
	unsigned long long n;
	scanf("%lld",&n);
	printf("%lld",n*(n-1)/2*(n-2)/3*(n-3)/4);
	return 0;
}
#include<iostream>
using namespace std;
int main(){
	unsigned long long n;
	cin>>n;
	cout<<n*(n-1)/2*(n-2)/3*(n-3)/4;
	return 0;
}
  • 解析:代码很短,定义一个变量,输入,输出就结束了,但有两个细节

    1. 用unsigned long long定义变量,因为题目要求3<=n<=100000;在极端情况下,n*(n-1)*(n-2)*(n-3)足足有10^19位数,很容易超出范围,所以必须要用范围尽可能大的数据类型

    2. 原本是n*(n-1)*(n-2)*(n-3)/24,但由于数据过大,直接算也很容易出错,所以这里把24拆分成2*3*4,变成n*(n-1)/2*(n-2)/3*(n-3)/4,每乘一次就除一下,保证数据尽可能不那么大

      还有一点就是必须按照2,3,4的顺序除,以免不能整除。n*(n-1)必定有一个数能被2整除,n*(n-1)*(n-2)必定有一个数能被3整除,n*(n-1)*(n-2)*(n-3)必定有一个数能被4整除。如果调换顺序,先除3或4,那么很有可能不能整除,导致最后结果出错

Java

import java.math.BigInteger;
import java.util.Scanner;
public class P2181_对角线 {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        BigInteger n = cin.nextBigInteger();
        BigInteger m;
        BigInteger o = n;
        for (int i = 1; i < 4; i++) {
            m = n.subtract(BigInteger.valueOf(i));
            o = m.multiply(o);
        }
        o = o.divide(BigInteger.valueOf(24));
        System.out.println(o);
        cin.close();
    }
}
  • 解析:相比C/C++,Java看起来要复杂一点,但其实不难,只有一个重点:用BigInteger定义变量

    • 在Java中可以使用BigInteger类来操作大整数,BigInteger是一个类,不能用+,-,*,/来运算,但可以用方法来计算

      BigInteger add(BigInteger val)表示+
      BigInteger subtract(BigInteger val)表示-
      BigInteger multiply(BigInteger val)表示*
      BigInteger divide(BigInteger val)表示-
      
    • 还有其他很多操作方法,网上搜一下BigInteger就有

    • 最后做除操作的时候没有像C/C++那样分成2,3,4来除,这是因为BigInteger是不可变的任意精度整数,能存储的数据上限很高,网上说是取决于电脑的内存,用在这里是绰绰有余了,而且每次运算的时候都要调用一次方法,分成3次写起来太麻烦了,所以这里就直接除24

posted @ 2021-04-25 21:57  杰达鲁  阅读(86)  评论(0编辑  收藏  举报