文章目錄
1. 題目描述
1.1. Limit
Time Limit: C/C++ 1秒,其他語言2秒
Memory Limit: C/C++ 262144K,其他語言524288K
1.2. Problem Description
平面上存在 條直線。請問 條直線在平面上最多存在多少交點。
1.3. Input
輸入數據的第一行是t,表示數據的組數 , 接下來每組數據輸入一個
1.4. Output
對於每組輸入樣例,打印 條直線最多有多少個交點
1.5. Sample Input
2
1
2
1.6. Sample Output
0
1
1.7. Source
2. 解讀
第 條線最多能和前 條線都相交,產生 個新的交點。
所以最終結果爲
但由於 的數據範圍很大 ,所以要使用高精度進行計算。高精度模板參考自百度百科-高精度算法。
3. 代碼
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
struct Wint : vector<int> //用標準庫vector做基類,完美解決位數問題,同時更易於實現
{
//將低精度轉高精度的初始化,可以自動被編譯器調用
//因此無需單獨寫高精度數和低精度數的運算函數,十分方便
Wint(int n = 0) //默認初始化爲0,但0的保存形式爲空
{
push_back(n);
check();
}
Wint& check() //在各類運算中經常用到的進位小函數,不妨內置
{
while (!empty() && !back())
pop_back(); //去除最高位可能存在的0
if (empty())
return *this;
for (size_t i = 1; i < size(); ++i) //處理進位
{
(*this)[i] += (*this)[i - 1] / 10;
(*this)[i - 1] %= 10;
}
while (back() >= 10) {
push_back(back() / 10);
(*this)[size() - 2] %= 10;
}
return *this; //爲使用方便,將進位後的自身返回引用
}
};
//輸入輸出
istream& operator>>(istream& is, Wint& n)
{
string s;
is >> s;
n.clear();
for (int i = s.size() - 1; i >= 0; --i)
n.push_back(s[i] - '0');
return is;
}
ostream& operator<<(ostream& os, const Wint& n)
{
if (n.empty())
os << 0;
for (int i = n.size() - 1; i >= 0; --i)
os << n[i];
return os;
}
//比較,只需要寫兩個,其他的直接代入即可
//常量引用當參數,避免拷貝更高效
bool operator!=(const Wint& a, const Wint& b)
{
if (a.size() != b.size())
return 1;
for (int i = a.size() - 1; i >= 0; --i)
if (a[i] != b[i])
return 1;
return 0;
}
bool operator==(const Wint& a, const Wint& b)
{
return !(a != b);
}
bool operator<(const Wint& a, const Wint& b)
{
if (a.size() != b.size())
return a.size() < b.size();
for (int i = a.size() - 1; i >= 0; --i)
if (a[i] != b[i])
return a[i] < b[i];
return 0;
}
bool operator>(const Wint& a, const Wint& b)
{
return b < a;
}
bool operator<=(const Wint& a, const Wint& b)
{
return !(a > b);
}
bool operator>=(const Wint& a, const Wint& b)
{
return !(a < b);
}
//加法,先實現+=,這樣更簡潔高效
Wint& operator+=(Wint& a, const Wint& b)
{
if (a.size() < b.size())
a.resize(b.size());
for (size_t i = 0; i != b.size(); ++i)
a[i] += b[i];
return a.check();
}
Wint operator+(Wint a, const Wint& b)
{
return a += b;
}
//減法,返回差的絕對值,由於後面有交換,故參數不用引用
Wint& operator-=(Wint& a, Wint b)
{
if (a < b)
swap(a, b);
for (size_t i = 0; i != b.size(); a[i] -= b[i], ++i)
if (a[i] < b[i]) //需要借位
{
size_t j = i + 1;
while (!a[j])
++j;
while (j > i) {
--a[j];
a[--j] += 10;
}
}
return a.check();
}
Wint operator-(Wint a, const Wint& b)
{
return a -= b;
}
//乘法不能先實現*=,原因自己想
Wint operator*(const Wint& a, const Wint& b)
{
Wint n;
n.assign(a.size() + b.size() - 1, 0);
for (size_t i = 0; i != a.size(); ++i)
for (size_t j = 0; j != b.size(); ++j)
n[i + j] += a[i] * b[j];
return n.check();
}
Wint& operator*=(Wint& a, const Wint& b)
{
return a = a * b;
}
//除法和取模先實現一個帶餘除法函數
Wint divmod(Wint& a, const Wint& b)
{
Wint ans;
for (int t = a.size() - b.size(); a >= b; --t) {
Wint d;
d.assign(t + 1, 0);
d.back() = 1;
Wint c = b * d;
while (a >= c) {
a -= c;
ans += d;
}
}
return ans;
}
Wint operator/(Wint a, const Wint& b)
{
return divmod(a, b);
}
Wint& operator/=(Wint& a, const Wint& b)
{
return a = a / b;
}
Wint& operator%=(Wint& a, const Wint& b)
{
divmod(a, b);
return a;
}
Wint operator%(Wint a, const Wint& b)
{
return a %= b;
}
//順手實現一個快速冪,可以看到和普通快速冪幾乎無異
Wint pow(const Wint& n, const Wint& k)
{
if (k.empty())
return 1;
if (k == 2)
return n * n;
if (k.back() % 2)
return n * pow(n, k - 1);
return pow(pow(n, k / 2), 2);
}
int main()
{
int t;
Wint n;
cin >> t;
while (t--) {
cin >> n;
cout << n * (n - 1) / 2 << endl;
}
}
聯繫郵箱:[email protected]
CSDN:https://me.csdn.net/qq_41729780
知乎:https://zhuanlan.zhihu.com/c_1225417532351741952
公衆號:複雜網絡與機器學習
歡迎關注/轉載,有問題歡迎通過郵箱交流。