#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <limits.h>
#define EPS 1e-9 //浮点比较
#define MOD 998244353 //取模运算
#define MAX_LL 1000010//大型数组
#define MAX_L 1010 //小型数组
#define MAX_N 11 //矩阵阶数
#define PI 3.141592653//通用常数
#define EU 2.718281828//通用常数
#define in int
#define ll long long
#define db double
#define ch char
#define vd void
#define uin unsigned int
#define ull unsigned long long
#define uch unsigned char
#define br break
#define cn continue
#define rt return
#define sc scanf
#define pr printf
//支持单元输入
#define scin(x) sc("%d", &(x))
#define scll(x) sc("%lld", &(x))
#define scdb(x) sc("%lf", &(x))
//支持空白略去
#define scch(x) sc(" %c", &(x))
#define scst(x) sc(" %s", (x))
//支持二元输入
#define scin2(x,y) sc("%d%d", &(x), &(y))
#define scll2(x,y) sc("%lld%lld", &(x), &(y))
#define scdb2(x,y) sc("%lf%lf", &(x), &(y))
//支持一元输出
#define prin(x) pr("%d", x)
#define prll(x) pr("%lld", x)
#define prdb(x) pr("%lf", x)
#define prch(x) pr("%c", x)
#define prst(x) pr("%s", x)
//支持一元换行输出
#define prinn(x) pr("%d\n", x)
#define prlln(x) pr("%lld\n", x)
#define prdbn(x) pr("%lf\n", x)
#define prchn(x) pr("%c\n", x)
#define prstn(x) pr("%s\n", x)
//支持一元精度输出
#define prdbr(x, r) pr("%.*lf", (r), (x))
//支持一元精度换行输出
#define prdbnr(x, r) pr("%.*lf\n", (r), (x))
//支持换行输出
#define prn pr("\n")
//支持空格输出
#define prb pr(" ")
//支持最值判断
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
//支持浮点相等判断
#define CEPS(a, b) (fabs((a) - (b)) < EPS)
//函数主体
//输入输出辅助
//高效输入(大量数据读取)
in fast_read()
{
in x = 0, f = 1;
ch c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -f;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
rt x* f;
}
//辅助一维数组输入([0,n))
vd sc_arr1(in arr[], in n)
{
for (in i = 0; i < n; i++)
{
scin(arr[i]);
}
}
//辅助一维数组输出([0,n))(自动去除换行符号)
vd pr_arr1(in arr[], in n)
{
for (in i = 0; i < n; i++)
{
pr("%d%c ", arr[i], " \n"[i == n - 1]);
}
}
//辅助二维数组输入([0,n))(嵌fast_read)
vd sc_arr2(in arr[][MAX_N], in row, in col)
{
for (in i = 0; i < row; i++)
{
for (in j = 0; j < col; j++)
{
arr[i][j] = fast_read();
}
}
}
//辅助二维数组输出([0,n))
vd pr_arr2(in arr[][MAX_N], in row, in col)
{
for (in i = 0; i < row; i++)
{
for (in j = 0; j < col; j++)
{
pr("%d ", arr[i][j]);
}
pr("\n");
}
}
//基础数学计算
//计算模加法/减法
ll norm(ll x)
{//工具函数(映射到[0,MOD-1];处理负数)
rt(x % MOD + MOD) % MOD;
}
ll mod_add(ll a, ll b)
{//模加法
rt norm(a + b);
}
ll mod_sub(ll a, ll b)
{//模减法
rt norm(a - b);
}
//计算模乘法(快速版)
ll mod_qmul(ll a, ll b)
{
a %= MOD;
b %= MOD;
ll res = 0;
while (b > 0)
{
if (b & 1)
{
res = (res + a) % MOD;
}
a = (a << 1) % MOD;
b >>= 1;
}
rt res;
}
//计算模乘法(基础版)
ll mod_fmul(ll a, ll b)
{
rt((a % MOD) * (b % MOD)) % MOD;
}
//计算斐波那契数列第n个数(非递归)
ll fibonacci1(in n)
{
if (n == 0) rt 0;
if (n == 1) rt 1;
ll prev = 0;
ll curr = 1;
ll next;
for (in i = 2; i <= n; i++)
{
next = prev + curr;
prev = curr;
curr = next;
}
rt curr;
}
//计算斐波那契数列第n个数(仅递归)
ll fibonacci2(in n)
{
if (n == 0)
{
rt 0;
}
else if (n == 1 || n == 2)
{
rt 1;
}
rt fibonacci2(n - 1) + fibonacci2(n - 2);
}
//计算斐波那契数列第n个数(递归;预存储;重复调用;取模;小n;越界MAX_L#-1)
ll mem[MAX_L] = { 0 };//存储数组
ll vis[MAX_L] = { 0 };//记忆数组
vd reset()
{//初始化记忆数组
memset(vis, 0, sizeof(vis));
}
ll fibonacci_mem(in n)
{//(嵌mod_add)
if (n < 0 || n >= MAX_L)
rt -1;
if (n == 0)
rt 0;
if (n == 1)
rt 1;
if (vis[n])
rt mem[n];
mem[n] = mod_add(fibonacci_mem(n - 1), fibonacci_mem(n - 2));
vis[n] = 1;
rt mem[n];
}
//计算斐波那契数列第n个数(迭代;非存储;单次调用;取模;大n;越界MAX_L#-1)
ll fib_iterative(in n)
{
if (n < 0 || n >= MAX_L)
return -1;
if (n == 0) return 0;
if (n == 1) return 1;
ll f0 = 0, f1 = 1;
for (in i = 2; i <= n; ++i)
{
ll f2 = mod_add(f0, f1);
f0 = f1;
f1 = f2;
}
return f1;
}
//计算给定数n的阶乘(非递归;取模;错误#-1)
ll factorial1(in n)
{
if (n < 0)
rt - 1;
ll result = 1;
for (in i = 2; i <= n; i++)
{
result = ((result % MOD) * (i % MOD)) % MOD;
}
rt result;
}
//计算给定数n的阶乘(仅递归;取模)
ll factorial2(in n)
{
if (n <= 1)
{
rt 1;
}
rt((n % MOD) * (factorial2(n - 1) % MOD)) % MOD;
}
//计算排列数P(对n排k;取模;错误#-1)
ll Per(in n, in k)
{
if (k < 0 || n < 0 || k > n)
{
rt - 1;
}
ll result = 1;
for (in i = n - k + 1; i <= n; i++)
{
result = (result * i) % MOD;
}
rt result;
}
//计算组合数C(对n组k;特殊;错误#-1)
ll Com_sp(in n, in k)
{
if (k < 0 || n < 0 || k > n)
{
rt - 1;
}
if (k > n - k)
{
k = n - k;
}
ll result = 1;
for (in i = 0; i < k; i++)
{
result = result * (static_cast<long long>(n) - i) / (static_cast<long long>(i) + 1);
}
rt result;
}
//计算幂次(快速幂)(base的exp次方;取模)
ll pow_mod(ll base, ll exp)
{
ll result = 1;
while (exp > 0)
{
if (exp & 1)
{
result = (result * base) % MOD;
}
base = (base * base) % MOD;
exp >>= 1;
}
rt result;
}
//计算二元最大公因数(绝对值)
ll gcd2(ll a, ll b)
{
if (a < 0)
a = -a;
if (b < 0)
b = -b;
while (b != 0)
{
ll temp = b;
b = a % b;
a = temp;
}
rt a;
}
//计算三元最大公因数(嵌gcd2)
ll gcd3(ll a, ll b, ll c)
{
rt gcd2(gcd2(a, b), c);
}
//计算n元最大公因数(数组[1,n);嵌gcd2)
ll gcdn(ll arr[], in n)
{
if (n == 0) rt 0;
ll result = arr[0];
for (in i = 1; i < n; ++i)
{
result = gcd2(result, arr[i]);
if (result == 1) br;
}
rt result;
}
//计算二元最小公倍数(嵌gcd2)
ll lcm2(ll a, ll b)
{
if (a == 0 || b == 0) rt 0;
ll ga = a < 0 ? -a : a;
ll gb = b < 0 ? -b : b;
ll g = gcd2(ga, gb);
rt ga / g * gb;
}
//计算三元最小公倍数(嵌lcm2)
ll lcm3(ll a, ll b, ll c)
{
rt lcm2(lcm2(a, b), c);
}
//计算n元最小公倍数(数组[1,n);嵌lcm2)
ll lcmn(ll arr[], in n)
{
if (n == 0) rt 1;
ll result = arr[0];
for (in i = 1; i < n; ++i)
{
result = lcm2(result, arr[i]);
if (result == 0) br;
}
rt result;
}
//基础数学判断
//判断x是否为回文数(是#1;否#0)
in is_palindrome(in x)
{
if (x < 0) rt 0;
in original = x;
in reversed = 0;
while (x > 0)
{
reversed = reversed * 10 + x % 10;
x /= 10;
}
rt original == reversed;
}
//判断x是否为斐波那契数(是#1;否#0)
in is_fibonacci(in x)
{
if (x < 0) rt 0;
if (x == 0 || x == 1) rt 1;
in a = 0, b = 1;
while (b < x)
{
in next = a + b;
a = b;
b = next;
}
rt b == x;
}
//判断x是否为阶乘数(是#1;否#0)
in is_factorial(in x)
{
if (x <= 0) rt 0;
in fact = 1;
for (in i = 1; ; ++i)
{
fact *= i;
if (fact == x) rt 1;
if (fact > x) rt 0;
}
}
//判断x是否为完全平方数(是#1;否#0)
in is_psquare(in x)
{
if (x < 0) rt 0;
in root = (in)sqrt((long double)x) + 0.5;
rt root* root == x;
}
//判断x是否为素数(是#1;否#0)
in is_prime(in x)
{
if (x <= 1)
{
rt 0;
}
else if (x <= 3)
{
rt 1;
}
else if (x % 2 == 0 || x % 3 == 0)
{
rt 0;
}
for (in i = 5; i * i <= x; i += 6)
{
if (x % i == 0 || x % (i + 2) == 0)
{
rt 0;
}
}
rt 1;
}
//判断x是否为2的自然数幂次(是#1;否#0)
in is_power2(in x)
{
rt x > 0 && (x & (x - 1)) == 0;
}
//任意进制转换
//10进制转2进制(正数;数字转数字版)
ll to_bin(ll n)
{
if (n == 0) rt 0LL;
ll bin = 0;
ll base = 1;
while (n > 0)
{
bin += (n % 2) * base;
n /= 2;
base *= 10;
}
rt bin;
}
//10进制转2进制(正数;数字转数组版;存入arr;低位在前;#二进制位数>0)
in to_bin_arrl(ll n, in arr[])
{
if (n == 0)
{
arr[0] = 0;
rt 1;
}
in i = 0;
while (n > 0)
{
arr[i++] = n % 2;
n /= 2;
}
rt i;
}
//10进制转2进制(正数;数字转数组版;存入arr;高位在前;#二进制位数>0)
in to_bin_arrh(ll n, in arr[])
{
if (n == 0)
{
arr[0] = 0;
rt 1;
}
in temp[64];
in len = 0;
while (n > 0)
{
temp[len++] = n % 2;
n /= 2;
}
for (in i = 0; i < len; ++i)
{
arr[i] = temp[len - 1 - i];
}
rt len;
}
//10进制转2进制(正数;数组转数组版;len位dec;存入bin;低位在前;#二进制位数>0)
in to_bin_2arrl(in dec[], in bin[], in len)
{
in work[MAX_L];
in temp[MAX_L];
in bin_len = 0;
for (in i = 0; i < len; ++i)
{
work[i] = dec[i];
}
while (1)
{
in all_zero = 1;
for (in i = 0; i < len; ++i)
{
if (work[i] != 0)
{
all_zero = 0;
br;
}
}
if (all_zero) rt bin_len;
in carry = 0;
for (in i = 0; i < len; ++i)
{
carry = carry * 10 + work[i];
temp[i] = carry / 2;
carry %= 2;
}
bin[bin_len++] = carry;
for (in i = 0; i < len; ++i)
{
work[i] = temp[i];
}
}
}
//10进制转2进制(正数;数组转数组版;len位dec;存入bin;高位在前;#二进制位数>0)
in to_bin_2arrh(in dec[], in bin[], in len)
{
in work[MAX_L];
in temp[MAX_L];
in bits[MAX_L];
in bit_len = 0;
for (in i = 0; i < len; ++i)
{
work[i] = dec[i];
}
while (1)
{
in all_zero = 1;
for (in i = 0; i < len; ++i)
{
if (work[i] != 0)
{
all_zero = 0;
br;
}
}
if (all_zero) br;
in carry = 0;
for (in i = 0; i < len; ++i)
{
carry = carry * 10 + work[i];
temp[i] = carry / 2;
carry %= 2;
}
bits[bit_len++] = carry;
for (in i = 0; i < len; ++i)
{
work[i] = temp[i];
}
}
if (bit_len == 0)
{
bin[0] = 0;
rt 1;
}
for (in i = 0; i < bit_len; ++i)
{
bin[i] = bits[bit_len - 1 - i];
}
rt bit_len;
}
//10进制转2进制(正数;数串转数组版;串num_str;存入bin;低位在前;#二进制位数>0)
in str_to_dgt1(const char* str, in digits[])
{//Tool.字符串转数组(#有效长度)
in len = 0;
while (str[len] != '\0')
{
if (str[len] >= '0' && str[len] <= '9')
digits[len] = str[len] - '0';
else
br;
++len;
}
rt len;
}
in to_bin_strl(const char* num_str, in bin[])
{//Main.数串转数组(#二进制位数)(嵌str_to_dgt1,to_bin_2arrl)
if (num_str == NULL || *num_str == '\0')
{
bin[0] = 0;
rt 1;
}
in digits[MAX_L];
in d_len = str_to_dgt1(num_str, digits);
in all_zero = 1;
for (in i = 0; i < d_len; ++i)
{
if (digits[i] != 0)
{
all_zero = 0;
br;
}
}
if (all_zero)
{
bin[0] = 0;
rt 1;
}
rt to_bin_2arrl(digits, bin, d_len);
}
//10进制转2进制(正数;数串转数组版;串num_str;存入bin;高位在前;#二进制位数>0)
in str_to_dgt2(const char* str, in digits[])
{//Tool.字符串转数组(#有效长度)
in len = 0;
while (str[len] != '\0')
{
if (str[len] >= '0' && str[len] <= '9')
digits[len] = str[len] - '0';
else
br;
++len;
}
rt len;
}
in to_bin_strh(const char* num_str, in bin[])
{//Main.数串转数组(#二进制位数)(嵌str_to_dgt2,to_bin_2arrh)
if (num_str == NULL || *num_str == '\0')
{
bin[0] = 0;
rt 1;
}
in digits[MAX_L];
in d_len = str_to_dgt2(num_str, digits);
in all_zero = 1;
for (in i = 0; i < d_len; ++i)
{
if (digits[i] != 0)
{
all_zero = 0;
br;
}
}
if (all_zero)
{
bin[0] = 0;
rt 1;
}
rt to_bin_2arrh(digits, bin, d_len);
}
//任意进制转换(2~36间;正数;字符串n转字符组m;错误#-1;正确#0(可忽略rt))
in char_to_value(ch c)
{//Tool.字符转数字
if (isdigit(c)) rt c - '0';
if (isupper(c)) rt c - 'A' + 10;
if (islower(c)) rt c - 'a' + 10;
rt - 1;
}
ch value_to_char(in val)
{//Tool.数字转字符
if (val < 10) rt '0' + val;
rt 'A' + val - 10;
}
in convert_base(const ch* n, in a, in b, ch m[])
{//Main.任意进制转换(嵌char_to_value,value_to_char)
if (!n || !m || a < 2 || a > 36 || b < 2 || b > 36)
{
if (m) m[0] = '\0';
rt - 1;
}
in len = strlen(n);
if (len == 0)
{
m[0] = '0'; m[1] = '\0';
rt 0;
}
ll decimal = 0;
for (in i = 0; i < len; ++i)
{
in val = char_to_value(n[i]);
if (val == -1 || val >= a)
{
m[0] = '\0';
rt - 1;
}
if (decimal > (LLONG_MAX - val) / a)
{
m[0] = '\0';
rt - 1;
}
decimal = decimal * a + val;
}
if (decimal == 0)
{
m[0] = '0';
m[1] = '\0';
rt 0;
}
ch temp[65];
in idx = 0;
while (decimal > 0)
{
in r = decimal % b;
temp[idx++] = value_to_char(r);
decimal /= b;
}
temp[idx] = '\0';
for (in i = 0; i < idx; ++i)
{
m[i] = temp[idx - 1 - i];
}
m[idx] = '\0';
rt 0;
}
//字符串综合
//判断字符串str是否为回文序列(是#1)
in is_palindrome(const ch* str)
{
if (str == NULL)
{
rt 0;
}
in left = 0;
in right = strlen(str) - 1;
while (left < right)
{
if (str[left] != str[right])
{
rt 0;
}
left++;
right--;
}
rt 1;
}
//要求反转字符串str(整体;破坏性)
vd rev_str_all(ch* str)
{
if (str == NULL)
{
rt;
}
in left = 0;
in right = strlen(str) - 1;
ch temp;
while (left < right)
{
temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
}
//要求反转字符串str(字串start到end;破坏性)
vd rev_str_range(ch* str, in start, in end)
{
if (str == NULL || start < 0 || end < 0 || start >= end) rt;
while (start < end)
{
ch temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
//要求字符串str前端删去n字符(str[0~n-1];破坏性)
vd det_frt_n(ch str[], in n)
{
if (str == NULL) rt;
in len = strlen(str);
if (n <= 0) rt;
if (n >= len)
{
str[0] = '\0';
rt;
}
for (in i = n; i <= len; ++i)
{
str[i - n] = str[i];
}
}
//要求字符串str末端删去n字符(str[len-n~len-1];破坏性)
vd det_end_n(ch str[], in n)
{
if (str == NULL) rt;
in len = strlen(str);
if (n <= 0) rt;
if (n >= len)
{
str[0] = '\0';
rt;
}
str[len - n] = '\0';
}
//要求字符串str删去m~n之间字符(str[m~n];破坏性)
vd det_range(ch str[], in m, in n)
{
if (str == NULL) rt;
in len = strlen(str);
if (m < 1 || n < m) rt;
if (n > len) n = len;
in start_idx = m - 1;
in end_idx = n - 1;
if (start_idx >= len) rt;
in del_len = end_idx - start_idx + 1;
for (in i = end_idx + 1; i <= len; ++i)
{
str[i - del_len] = str[i];
}
}
//数组综合
//求数组元素和(arr;[0,n-1];取模;嵌mod_add)
ll sum_arr_mod(const in arr[], in n)
{
ll s = 0;
for (in i = 0; i < n; i++)
{
s = mod_add(s, arr[i]);
}
rt s;
}
//求数组元素积(arr;[0,n-1];取模;嵌mod_qmul)
ll prod_arr_mod(const in arr[], in n)
{
ll p = 1;
for (in i = 0; i < n; i++)
{
p = mod_qmul(p, arr[i]);
}
rt p;
}
//反转数组(arr;[0,n-1];破坏性)
vd reverse_arr(in arr[], in n)
{
for (in i = 0; i < n / 2; i++)
{
in t = arr[i];
arr[i] = arr[n - 1 - i];
arr[n - 1 - i] = t;
}
}
//对排序数组去重(src[0,srcSize-1]存入dest[0,*destSize-1])
vd remove_same(const ll src[], in srcSize, ll dest[], in* destSize)
{
if (srcSize == 0)
{
*destSize = 0;
rt;
}
dest[0] = src[0];
in count = 1;
for (in i = 1; i < srcSize; ++i)
{
if (src[i] != src[i - 1])
{
dest[count++] = src[i];
}
}
*destSize = count;
}
//求数组的逆序数(arr;[0,n-1];破坏性)
in temp_arr[MAX_L];//临时数组
vd merge_sort_inv(in arr[], in left, in right, in* inv_count)
{//内层函数(归并排序)(对arr[left,right]求逆序)
if (left >= right) rt;
in mid = (left + right) / 2;
merge_sort_inv(arr, left, mid, inv_count);
merge_sort_inv(arr, mid + 1, right, inv_count);
in i = left, j = mid + 1, k = left;
while (i <= mid && j <= right)
{
if (arr[i] <= arr[j])
{
temp_arr[k++] = arr[i++];
}
else
{
temp_arr[k++] = arr[j++];
*inv_count += (mid - i + 1);
}
}
while (i <= mid) temp_arr[k++] = arr[i++];
while (j <= right) temp_arr[k++] = arr[j++];
for (i = left; i <= right; i++) arr[i] = temp_arr[i];
}
in count_inversions(in arr[], in n)
{//外层函数(对arr[0,n-1]求逆序)
in inv_count = 0;
merge_sort_inv(arr, 0, n - 1, &inv_count);
rt inv_count;
}
//求数组的逆序数(arr;[0,n-1];非破坏性)
in temp_arr[MAX_L];//临时数组
in copy_arr[MAX_L];//副本数组
vd merge_sort_inv_nd(in arr[], in left, in right, in* inv_count)
{//内层函数(归并排序)(对arr[left,right]求逆序)
if (left >= right) rt;
in mid = (left + right) / 2;
merge_sort_inv_nd(arr, left, mid, inv_count);
merge_sort_inv_nd(arr, mid + 1, right, inv_count);
in i = left, j = mid + 1, k = left;
while (i <= mid && j <= right)
{
if (arr[i] <= arr[j])
{
temp_arr[k++] = arr[i++];
}
else
{
temp_arr[k++] = arr[j++];
*inv_count += (mid - i + 1);
}
}
while (i <= mid) temp_arr[k++] = arr[i++];
while (j <= right) temp_arr[k++] = arr[j++];
for (i = left; i <= right; i++) arr[i] = temp_arr[i];
}
in count_inversions_nd(const in arr[], in n)
{//外层函数(对arr[0,n-1]求逆序;非破坏性)
for (in i = 0; i < n; ++i) copy_arr[i] = arr[i];
in inv_count = 0;
merge_sort_inv_nd(copy_arr, 0, n - 1, &inv_count);
rt inv_count;
}
//求矩阵相乘(A(m*r)*B(r*n)=C(m*n))[0,m)
vd mat_mul(in A[][MAX_N], in B[][MAX_N], in C[][MAX_N], in m, in r, in n)
{
for (in i = 0; i < m; i++)
{
for (in j = 0; j < n; j++)
{
C[i][j] = 0;
}
}
for (in i = 0; i < m; i++)
{
for (in k = 0; k < r; k++)
{
for (in j = 0; j < n; j++)
{
C[i][j] += A[i][k] * B[k][j];
}
}
}
}
//求矩阵的余子式Mij(n阶,i=row,j=col除余子式)[0,m)
vd det_Mij(in A[][MAX_N], in Mij[][MAX_N], in row, in col, in n)
{
in i = 0, j = 0;
for (in r = 0; r < n; r++)
{
for (in c = 0; c < n; c++)
{
if (r != row && c != col)
{
Mij[i][j++] = A[r][c];
if (j == n - 1) {
j = 0;
i++;
}
}
}
}
}
//求矩阵的行列式det(n阶;嵌det_Mij))[0,m)
ll mat_det(in A[][MAX_N], in n)
{
in det = 0;
if (n == 1)
{
rt A[0][0];
}
if (n == 2)
{
rt A[0][0] * A[1][1] - A[0][1] * A[1][0];
}
in temp[MAX_N][MAX_N];
in sign = 1;
for (in f = 0; f < n; f++)
{
det_Mij(A, temp, 0, f, n);
det += sign * A[0][f] * mat_det(temp, n - 1);
sign *= -1;
}
rt det;
}
//求矩阵的转置(m行n列的A转置为T)[0,m)
vd mat_tran(in A[][MAX_N], in T[][MAX_N], in m, in n)
{
for (in i = 0; i < m; i++)
{
for (in j = 0; j < n; j++)
{
T[j][i] = A[i][j];
}
}
}
//求矩阵的秩(m行n列的A求rank;非破坏性)[0,m)
in mat_rank(ll A[][MAX_N], in m, in n)
{
ll work[MAX_N][MAX_N];
for (in i = 0; i < m; ++i)
{
for (in j = 0; j < n; ++j)
{
work[i][j] = A[i][j];
}
}
in rank = 0;
for (in col = 0; col < n && rank < m; ++col)
{
in pivot_row = -1;
for (in i = rank; i < m; ++i)
{
if (work[i][col] != 0)
{
pivot_row = i;
br;
}
}
if (pivot_row == -1) cn;
if (pivot_row != rank)
{
for (in j = 0; j < n; ++j)
{
ll temp = work[rank][j];
work[rank][j] = work[pivot_row][j];
work[pivot_row][j] = temp;
}
}
for (in r = rank + 1; r < m; ++r)
{
while (work[r][col] != 0)
{
ll abs_cur = llabs(work[r][col]);
ll abs_piv = llabs(work[rank][col]);
if (abs_cur >= abs_piv)
{
ll t = work[r][col] / work[rank][col];
if (t == 0) t = (work[r][col] > 0) ? 1 : -1;
for (in j = col; j < n; ++j)
{
work[r][j] -= t * work[rank][j];
}
}
else
{
for (in j = col; j < n; ++j)
{
ll temp = work[r][j];
work[r][j] = work[rank][j];
work[rank][j] = temp;
}
}
}
}
rank++;
}
rt rank;
}
//排序查找
//泛用交换函数
vd swap(in* a, in* b)
{
in temp = *a;
*a = *b;
*b = temp;
}
//泛用比较函数组(cmp)
typedef in(*cmp_fn)(const vd*, const vd*);
in incmp_up(const vd* a, const vd* b)
{//int升序
in x = *(const in*)a;
in y = *(const in*)b;
if (x < y) rt - 1;
if (x > y) rt 1;
rt 0;
}
in incmp_dn(const vd* a, const vd* b)
{//int降序(嵌incmp_up)
rt - incmp_up(a, b);
}
in chcmp_as(const vd* a, const vd* b)
{//char字典序
uch x = *(const uch*)a;
uch y = *(const uch*)b;
rt(x > y) - (x < y);
}
//冒泡排序(升序;单元;嵌swap)[0,n)
vd bubble_sort(in* arr, size_t n)
{
if (arr == NULL || n < 2)
{
rt;
}
for (size_t i = 0; i < n - 1; i++)
{
in swapped = 0;
for (size_t j = 0; j < n - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
swap(&arr[j], &arr[j + 1]);
swapped = 1;
}
}
if (!swapped)
{
break;
}
}
}
//快速排序(基础版本;非cmp升序;单元;嵌swap)[l,r]
vd quick_sort(in arr[], in l, in r)
{
if (l >= r)
{
rt;
}
in i = l, j = r;
in pivot = arr[(l + r) / 2];
while (i <= j)
{
while (arr[i] < pivot) i++;
while (arr[j] > pivot) j--;
if (i <= j)
{
swap(&arr[i], &arr[j]);
i++;
j--;
}
}
quick_sort(arr, l, j);
quick_sort(arr, i, r);
}
//快速排序(优化重复;非cmp升序;单元;嵌swap)[l,r]
vd quick_sort_3w(in arr[], in l, in r)
{
if (l >= r) rt;
in pivot = arr[l];
in lt = l;
in gt = r;
in i = l;
while (i <= gt)
{
if (arr[i] < pivot)
swap(&arr[i++], &arr[lt++]);
else if (arr[i] > pivot)
swap(&arr[i], &arr[gt--]);
else
i++;
}
quick_sort_3w(arr, l, lt - 1);
quick_sort_3w(arr, gt + 1, r);
}
//快速排序(基础版本;cmp升序版;单元;嵌swap;嵌自定义cmp)[l,r]
vd quick_csort(in arr[], in l, in r, cmp_fn cmp)
{//调用时:quick_csort(arr,l,r,incmp_up)
if (l >= r)
{
rt;
}
in i = l, j = r;
in pivot = arr[(l + r) / 2];
while (i <= j)
{
while (cmp(&arr[i], &pivot) < 0) i++;
while (cmp(&arr[j], &pivot) > 0) j--;
if (i <= j)
{
swap(&arr[i], &arr[j]);
i++;
j--;
}
}
quick_csort(arr, l, j, cmp);
quick_csort(arr, i, r, cmp);
}
//快速排序(优化重复;cmp升序版;单元;嵌swap;嵌自定义cmp)[l,r]
vd quick_csort_3w(in arr[], in l, in r, cmp_fn cmp)
{//调用时:quick_csort_3w(arr,l,r,incmp_up)
if (l >= r) rt;
in pivot = arr[l];
in lt = l;
in gt = r;
in i = l;
while (i <= gt)
{
in res = cmp(&arr[i], &pivot);
if (res < 0)
swap(&arr[i++], &arr[lt++]);
else if (res > 0)
swap(&arr[i], &arr[gt--]);
else
i++;
}
quick_csort_3w(arr, l, lt - 1, cmp);
quick_csort_3w(arr, gt + 1, r, cmp);
}
//二分查找(预升序;找x;成功#arr下标;失败#-1)[0,n)
in bin_search(in arr[], in n, in x)
{
in left = 0, right = n - 1;
while (left <= right)
{
in mid = left + (right - left) / 2;
if (arr[mid] == x)
rt mid;
else if (arr[mid] < x)
left = mid + 1;
else
right = mid - 1;
}
rt -1;
}
//二分求解(对预设函数求单零点;常规;成功#解;失败#NAN)[low,high]
db test_func1(db x)
{//函数示例:x*x-2=0
return x * x - 2;
}
db bin_solve(db low, db high, db(*f)(db))
{//调用示例:bin_solve(low,high,test_func1)
db fl = f(low), fh = f(high);
if (fl * fh > 0) return NAN;
while (high - low > EPS)
{
db mid = (low + high) / 2;
db fm = f(mid);
if (fm == 0) rt mid;
if (fm * fl > 0)
{
low = mid;
fl = fm;
}
else
{
high = mid;
}
}
return (low + high) / 2;
}
//二分求解(对预设函数求单零点;递归;成功#解;失败#NAN)[low,high]
db test_func2(db x)
{//函数示例:x*x-2=0
return x * x - 2;
}
db bin_solve_s(db low, db high)
{
db fl = test_func2(low), fh = test_func2(high);
if (fl * fh > 0)
{
return NAN;
}
db mid = (low + high) / 2;
db fm = test_func2(mid);
if (high - low < EPS)
{
return mid;
}
if (fm * fl > 0)
{
return bin_solve_s(mid, high);
}
else
{
return bin_solve_s(low, mid);
}
}
//几何综合
//判断三点是否共线(xi,yi)(否#0)
in is_line(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3)
{
ll cross = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
rt cross == 0;
}
//判断点是否在线段上((x,y)在(x1,y1)(x2,y2)上;否#0)(嵌is_line)
in is_pline(ll x, ll y, ll x1, ll y1, ll x2, ll y2)
{
if (!is_line(x, y, x1, y1, x2, y2)) rt 0;
rt(x >= MIN(x1, x2) && x <= MAX(x1, x2) &&
y >= MIN(y1, y2) && y <= MAX(y1, y2));
}
//判断两线段是否相交((x1,y1)(x2,y2)与(x3,y3)(x4,y4);否#0)
ll cross_point(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3)
{//内层函数
rt(x2 - x1)* (y3 - y1) - (x3 - x1) * (y2 - y1);
}
in is_cline(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3, ll x4, ll y4)
{//外层函数(嵌corss_point)
if (MAX(x1, x2) < MIN(x3, x4) || MAX(x3, x4) < MIN(x1, x2) ||
MAX(y1, y2) < MIN(y3, y4) || MAX(y3, y4) < MIN(y1, y2))
rt 0;
ll c1 = cross_point(x1, y1, x2, y2, x3, y3);
ll c2 = cross_point(x1, y1, x2, y2, x4, y4);
ll c3 = cross_point(x3, y3, x4, y4, x1, y1);
ll c4 = cross_point(x3, y3, x4, y4, x2, y2);
rt(c1 * c2 <= 0) && (c3 * c4 <= 0);
}
//计算平面上两点的距离(x1,y1)(x2,y2)
db dis_d2(db x1, db y1, db x2, db y2)
{
db dx = x2 - x1;
db dy = y2 - y1;
rt sqrt(dx * dx + dy * dy);
}
//计算立体上两点的距离(xi,yi)
db dis_d3(db x1, db y1, db z1, db x2, db y2, db z2)
{
db dx = x2 - x1;
db dy = y2 - y1;
db dz = z2 - z1;
rt sqrt(dx * dx + dy * dy + dz * dz);
}
//计算三角形面积(整坐标二倍防浮点)(xi,yi)
ll tri_2s(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3)
{
ll area_2 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
rt area_2 < 0 ? -area_2 : area_2;
}
//计算凸多边形面积(整坐标二倍防浮点)(x[i],y[i],[0,n-1])
ll ply_2s(in n, ll x[], ll y[])
{
ll area_2 = 0;
for (in i = 0; i < n; ++i)
{
in j = (i + 1) % n;
area_2 += x[i] * y[j] - x[j] * y[i];
}
rt llabs(area_2);
}
//计算三角形周长(xi,yi);嵌dis_d2)
db tri_c(db x1, db y1, db x2, db y2, db x3, db y3)
{
db ab = dis_d2(x1, y1, x2, y2);
db bc = dis_d2(x2, y2, x3, y3);
db ca = dis_d2(x3, y3, x1, y1);
rt ab + bc + ca;
}
//计算多边形周长(x[i],y[i],[0,n-1];嵌dis_d2)
db ply_c(in n, db x[], db y[])
{
db p = 0;
for (in i = 0; i < n; ++i)
{
in j = (i + 1) % n;
p += dis_d2(x[i], y[i], x[j], y[j]);
}
rt p;
}
//时间日期
//判断某年是否为闰年
in is_leap(in year)
{
rt(year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
}
//求某年某月的天数(switch;嵌is_leap)
in d_of_m_sw(in year, in month)
{
in days = 0;
switch (month)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
days = 31;
break;
case 4: case 6: case 9: case 11:
days = 30;
break;
case 2:
days = is_leap(year) ? 29 : 28;
break;
}
rt days;
}
//求某年某月的天数(array;嵌is_leap)
in d_of_m_ar(in year, in month)
{
if (month < 1 || month > 12) rt - 1;
const in days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
in d = days[month];
if (month == 2 && is_leap(year)) d++;
rt d;
}
//求某日期是该年第几天(嵌d_of_m_ar)
in d_of_y(in year, in month, in day)
{
in total = 0;
for (in i = 1; i < month; ++i)
{
total += d_of_m_ar(year, i);
}
rt total + day;
}
//求某日期对应的星期数(周日#0)
in week(in year, in month, in day)
{
if (month < 3)
{
year--;
month += 12;
}
in century = year / 100;
year %= 100;
in w = (year + year / 4 + century / 4 - 2 * century + (26 * (month + 1)) / 10 + day) % 7;
if (w < 0) w += 7;
rt(w + 6) % 7;
}审核下
最新发布