10184602226 edited 3 年,9 月前
This is a past version of blog 模板2
#include "pch.h"
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <string>
#include <functional>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <string.h>
using namespace std;
const long double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446;
//****************************模板BEGIN***********************************
class StringUtil {
public:
//用c来分割s,返回分割后的一个个字符串
vector<string> split(string s, char c);
//去除一个字符串前后的空格
string trim(string s);
//把一个字符串转换为字符vector
vector<char> toCharVector(string s);
//把一个字符vector转换为字符串
string vectorToString(vector<char> v);
//专门用来分割空格
vector<string> splitBlank(string s);
};
class BigNumUtil {
public:
//两个超大正整数的加法
string bigDecimalAdd(string num1, string num2);
//两个超大正整数的乘法
string bigDecimalMultiply(string num1, string num2);
//两个超大正整数的减法,注意需要num1≥num2
string bigDecimalMinus(string num1, string num2);
//两个超大正整数的除法,小数部分为零的话就不会显示,如果除不尽,cir_start和cir_end指出了循环节的首尾(小数点后第x位到小数点后第y位)
string bigDecimalDivide(string up, string down, int& cir_start, int& cir_end);
//超大正整数的Cnm
string bigDecimalCnm(int n, int m);
//两个超大正整数比较大小
int bigDecimalCompare(string num1, string num2);
};
class MathUtil {
public:
//最大公约数
int getLCM(int a, int b);
//最小公倍数
int getGCD(int a, int b);
//计算kBase^kExp
unsigned long long pow(unsigned long long const kBase, unsigned long long const kExp);
//计算Cnm
unsigned long long combine(int n, int m);
//大数情况,计算kBase^kExp再对kMod取余后的结果
unsigned long long powAndMod(unsigned long long const kBase, unsigned long long const kExp, unsigned long long const kMod);
//大数情况,下面三个函数都是为了计算 Cnm%mod 的,用第三个就行
unsigned long long exp_mod(unsigned long long a, unsigned long long b, unsigned long long p);
unsigned long long Comb(unsigned long long a, unsigned long long b, unsigned long long p);
unsigned long long combineAndMod(unsigned long long n, unsigned long long m, unsigned long long mod);
};
//专门用来求解二项式(ax+by)^k中x^n*y^m的系数,通式为Ckn*a^n*b^m
class PolynomialUtil {
public:
//重点就在于把阶乘打表
vector<unsigned long long> factorial;
//这个构造方法最多使用一次,因为打表很花时间
//maxK指的是k的最大值,mod是指结果对多少取余,这两个参数题目一般都会给出,如果maxK不给那就取一个较大的值
PolynomialUtil(int maxK, unsigned long long mod);
unsigned long long go(unsigned long long a, unsigned long long b, unsigned long long k, unsigned long long n, unsigned long long m, unsigned long long mod);
};
//初始化一个m*n的二维数组,使用dtf填充,返回的vector可以当作数组一样使用
template<typename T>
vector<vector<T>> initMatrix(int m, int n, T dft);
//****************************模板END*************************************
int main() {
int T;
cin >> T;
for (int t = 0;t < T;t++) {
cout << "case #" << t << ":" << endl;
}
}
//****************************模板BEGIN***********************************
vector<string> StringUtil::split(string s, char c) {
vector<string> result;
int len = s.size();
string temp = "";
for (int i = 0;i < len;i++) {
if (s[i] != c) {
temp += s[i];
}
else {
result.push_back(temp);
temp = "";
}
}
if (temp != "") {
result.push_back(temp);
}
return result;
}
string StringUtil::trim(string s) {
string res = "";
int ptr = 0;
while (s[ptr] == ' ') {
ptr++;
}
while (ptr != s.size()) {
res += s[ptr++];
}
auto it = res.end() - 1;
while (*it == ' ') {
res.erase(it);
it--;
}
return res;
}
vector<char> StringUtil::toCharVector(string s) {
vector<char> res;
for (int i = 0;i < s.size();i++) {
res.push_back(s[i]);
}
return res;
}
string StringUtil::vectorToString(vector<char> v) {
string res = "";
for (char c : v) {
res += c;
}
return res;
}
vector<string> StringUtil::splitBlank(string s) {
vector<string> result;
s = StringUtil().trim(s);
int ptr = 0;
bool processChar = true;
string temp = "";
while (true) {
if (processChar) {
if (s[ptr] != ' ') {
temp += s[ptr];
ptr++;
}
else {
result.push_back(temp);
temp = "";
processChar = false;
}
}
else {
if (s[ptr] != ' ') {
temp += s[ptr];
processChar = true;
}
ptr++;
}
if (ptr == s.size()) {
if (temp != "") {
result.push_back(temp);
}
break;
}
}
return result;
}
string BigNumUtil::bigDecimalAdd(string num1, string num2) {
string s = num2;
string l = num1;
if (num1.size() <= num2.size()) {
s = num1;
l = num2;
}
int ssize = s.size();
int lsize = l.size();
int sptr = ssize - 1;
int lptr = lsize - 1;
vector<int> v;
int up = 0;
while (true) {
int digit1 = s[sptr--] - '0';
int digit2 = l[lptr--] - '0';
int cal = digit1 + digit2 + up;
if (cal >= 10) {
up = 1;
cal -= 10;
}
else {
up = 0;
}
v.push_back(cal);
if (sptr == -1) {
while (lptr != -1) {
cal = l[lptr--] - '0' + up;
if (cal >= 10) {
up = 1;
cal -= 10;
}
else {
up = 0;
}
v.push_back(cal);
}
if (up == 1) {
v.push_back(1);
}
break;
}
}
string res = "";
for (int i = v.size() - 1;i >= 0;i--) {
res += (v[i] + '0');
}
return res;
}
string BigNumUtil::bigDecimalMultiply(string num1, string num2) {
string s = num2;
string l = num1;
if (num1.size() <= num2.size()) {
s = num1;
l = num2;
}
int ssize = s.size();
int lsize = l.size();
vector<string> numList;
for (int i = ssize - 1;i >= 0;i--) {
stack<char> temp;
int digit1 = s[i] - '0';
int up = 0;
for (int j = lsize - 1;j >= 0;j--) {
int digit2 = l[j] - '0';
int cal = digit1 * digit2 + up;
if (cal >= 10) {
up = cal / 10;
cal = cal % 10;
}
else {
up = 0;
}
temp.push(cal + '0');
if (j == 0 && up != 0) {
temp.push(up + '0');
}
}
string res = "";
while (!temp.empty()) {
res += temp.top();
temp.pop();
}
//补上0,比如40*123时,那个0得在这里补上
for (int j = 0;j < ssize - 1 - i;j++) {
res += "0";
}
numList.push_back(res);
}
string res = "0";
for (int i = 0;i < numList.size();i++) {
res = BigNumUtil::bigDecimalAdd(res, numList[i]);
}
return res;
}
string BigNumUtil::bigDecimalMinus(string num1, string num2) {
if (num1 == num2) {
return "0";
}
int size1 = num1.size();
int size2 = num2.size();
int ptr1 = size1 - 1;
int ptr2 = size2 - 1;
int borrow = 0;
stack<char> stk;
while (true) {
int cal = num1[ptr1--] - '0' - (num2[ptr2--] - '0') - borrow;
if (cal < 0) {
borrow = 1;
cal += 10;
}
else {
borrow = 0;
}
stk.push(cal + '0');
if (ptr2 == -1) {
while (ptr1 != -1) {
int cal = num1[ptr1--] - '0' - borrow;
if (cal < 0) {
borrow = 1;
cal += 10;
}
else {
borrow = 0;
}
stk.push(cal + '0');
}
while (stk.top() == '0') {
stk.pop();
}
break;
}
}
string res = "";
while (!stk.empty()) {
res += stk.top();
stk.pop();
}
return res;
}
string BigNumUtil::bigDecimalDivide(string up, string down, int& cir_start, int& cir_end) {
if (up == "0") {
return "0";
}
if (up == down) {
return "1";
}
//准备好分母的所有倍数,后续可以直接取用
vector<string> timesOfDown;
timesOfDown.push_back("0");
timesOfDown.push_back(down);
for (int i = 2;i <= 10;i++) {
timesOfDown.push_back(bigDecimalMultiply(string(1, i + '0'), down));
}
int ptr = 0;
int upSize = up.size();
//被减数
string currentString = "";
string intPart = "";
//处理整数部分
if (bigDecimalCompare(up, down) == 1) {
while (true) {
if (ptr < upSize) {
currentString += up[ptr];
}
else if (ptr == upSize) {
//如果currentString不为"",说明整数部分除不尽,还有小数部分,现在的这个currentString就是后续处理小数部分时的分子
up = currentString;
break;
}
ptr++;
for (int i = 1;i < 11;i++) {
if (bigDecimalCompare(timesOfDown[i], currentString) == 1) {
//减数
string minu = timesOfDown[i - 1];
//商
intPart += (i - 1 + '0');
//作差
currentString = bigDecimalMinus(currentString, minu);
//余数为0,说明除尽了
if (currentString == "0") {
currentString = "";
}
break;
}
}
}
//去除前导0
auto it = intPart.begin();
while (*it == '0') {
intPart.erase(it);
}
}
if (up == "") {
return intPart;
}
else {
if (intPart == "") {
intPart = "0";
}
//被减数
currentString = up;
string floatPart = "";
//记录已经出现过的余数和第一次出现的位置(小数点后x位)
unordered_map<string, int> left;
int index = 0;
while (true) {
bool canStop = false;
index++;
for (int i = 1;i < 11;i++) {
if (bigDecimalCompare(timesOfDown[i], currentString) == 1) {
//减数
string minu = timesOfDown[i - 1];
//商
floatPart += (i - 1 + '0');
if (index == 1) {
floatPart += ".";
}
//作差
currentString = bigDecimalMinus(currentString, minu);
//如果是第一次出现的余数,加入到set中
if (left.find(currentString) == left.end()) {
left.insert(make_pair(currentString, index));
}
//否则,说明出现了循环节
else {
cir_start = left[currentString];
cir_end = index - 1;
canStop = true;
}
//余数为0,说明除尽了
if (currentString == "0") {
canStop = true;
}
currentString += "0";
break;
}
}
if (canStop) {
break;
}
}
return intPart + floatPart.substr(1);
}
}
int BigNumUtil::bigDecimalCompare(string num1, string num2) {
if (num1.size() > num2.size()) {
return 1;
}
if (num1.size() < num2.size()) {
return -1;
}
int ptr = 0;
while (ptr != num1.size()) {
if (num1[ptr] > num2[ptr]) {
return 1;
}
if (num1[ptr] < num2[ptr]) {
return -1;
}
ptr++;
}
return 0;
}
template<typename T>
vector<vector<T>> initMatrix(int m, int n, T dft) {
vector<vector<T>> matrix;
vector<T> row;
row.resize(n, dft);
matrix.resize(m, row);
return matrix;
}
int MathUtil::getLCM(int a, int b) {
int max = (a > b ? a : b);
int min = (a < b ? a : b);
int res = max % min;
while (res) {
max = min;
min = res;
res = max % min;
}
return min;
}
int MathUtil::getGCD(int a, int b) {
return a * b / getLCM(a, b);
}
unsigned long long MathUtil::powAndMod(unsigned long long const kBase, unsigned long long const kExp, unsigned long long const kMod) {
unsigned long long ret = 1;
for (unsigned long long i = kExp, base = kBase % kMod; i; i >>= 1) {
if (i & 1) {
ret = ret * base % kMod;
}
base = base * base % kMod;
}
return ret;
}
unsigned long long MathUtil::pow(unsigned long long const kBase, unsigned long long const kExp) {
unsigned long long ret = 1;
for (unsigned long long i = kExp, base = kBase; i; i >>= 1) {
if (i & 1) {
ret = ret * base;
}
base = base * base;
}
return ret;
}
unsigned long long MathUtil::exp_mod(unsigned long long a, unsigned long long b, unsigned long long p) {
long long res = 1;
while (b != 0) {
if (b & 1) res = (res * a) % p;
a = (a*a) % p;
b >>= 1;
}
return res;
}
unsigned long long MathUtil::Comb(unsigned long long a, unsigned long long b, unsigned long long p) {
if (a < b) return 0;
if (a == b) return 1;
if (b > a - b) b = a - b;
unsigned long long ans = 1, ca = 1, cb = 1;
for (unsigned long long i = 0; i < b; ++i) {
ca = (ca * (a - i)) % p;
cb = (cb * (b - i)) % p;
}
ans = (ca*exp_mod(cb, p - 2, p)) % p;
return ans;
}
unsigned long long MathUtil::combineAndMod(unsigned long long n, unsigned long long m, unsigned long long mod) {
unsigned long long ans = 1;
while (n&&m&&ans) {
ans = (ans*Comb(n%mod, m%mod, mod)) % mod;
n /= mod;
m /= mod;
}
return ans;
}
unsigned long long MathUtil::combine(int n, int m) {
if (m < n - m) m = n - m;
unsigned long long ans = 1;
for (int i = m + 1; i <= n; i++) ans *= i;
for (int i = 1; i <= n - m; i++) ans /= i;
return ans;
}
PolynomialUtil::PolynomialUtil(int maxK, unsigned long long mod) {
factorial.resize(maxK + 1);
factorial[0] = 1;
for (int i = 1; i < maxK + 1; ++i) {
factorial[i] = factorial[i - 1] * i % mod;
}
}
unsigned long long PolynomialUtil::go(unsigned long long a, unsigned long long b, unsigned long long k, unsigned long long n, unsigned long long m, unsigned long long mod) {
unsigned long long inv_binom = MathUtil().powAndMod(factorial[n] * factorial[m] % mod, mod - 2, mod);
unsigned long long apow = MathUtil().powAndMod(a, n, mod);
unsigned long long bpow = MathUtil().powAndMod(b, m, mod);
unsigned long long ans = factorial[k] * inv_binom % mod;
ans = ans * apow % mod;
ans = ans * bpow % mod;
return ans;
}
string BigNumUtil::bigDecimalCnm(int n, int m) {
string up = "1";
for (int i = 0;i < m;i++) {
up = BigNumUtil().bigDecimalMultiply(up, to_string(n - i));
}
string down = "1";
for (int i = 2;i <= m;i++) {
down = BigNumUtil().bigDecimalMultiply(down, to_string(i));
}
int useless;
return BigNumUtil().bigDecimalDivide(up, down, useless, useless);
}
//****************************模板END*************************************