1. 题目来源
链接:P2181 对角线
2. 题目说明
3. 题目解析
通过题目明确不会有三条对角线交于一点,可以得出一个交点有且仅有两条对角线。故可以推导得到这两条对角线可以唯一确定四个顶点。
即将问题转化为 n
个顶点中,取 4
个的方案数,也就是组合数公式
C
n
4
=
n
∗
(
n
−
1
)
∗
(
n
−
2
)
∗
(
n
−
3
)
24
C_{n}^{4} = \frac {n * (n-1) * (n-2) * (n-3) } {24}
Cn4=24n∗(n−1)∗(n−2)∗(n−3)
在此由于改变四个点的顺序不会改变对角线,所以是组合数而非排列数。
参照 lg
大佬的题解,学习了防溢出的方法,原式可等价变形为:
C
n
4
=
n
∗
(
n
−
1
)
2
∗
(
n
−
2
)
3
∗
(
n
−
3
)
4
C_{n}^{4} = n * \frac {(n-1)}{2} * \frac{(n-2)}{3} * \frac {(n-3)}{4}
Cn4=n∗2(n−1)∗3(n−2)∗4(n−3)
考虑上式除不尽而向下取整导致的错误:由 n n n 与 n − 1 n-1 n−1 这两数中其中有一个一定是 2 2 2 的倍数,所以 2 2 2 可以除尽,同理 n , n − 1 , n − 2 n, n - 1, n - 2 n,n−1,n−2 中一定有一个是 3 3 3 的倍数,因此 3 3 3 可以除尽,同理可得 4 4 4 也可以除尽。故为等价变形。
对角线公式: n ∗ ( n − 3 ) 2 \frac {n * (n - 3)}{2} 2n∗(n−3)
且针对这个数据范围不需要高精度,比 long long
大,但在 unsigned long long
中,仍需要等价变形,避免乘的时候溢出。
参见代码如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{
unsigned long long n;
cin >> n;
cout << n * (n-1) / 2 * (n-2) / 3 * (n-3) / 4 << endl;
return 0;
}