首页
模数(int)¶
template <typename P = int, typename Q = long long, P MOD = 998244353>
class MInt {
public:
static P selfPow(P base, P p) {
Q ret = 1;
while (p) {
if (p & 1)
ret = (ret * base) % MOD;
p >>= 1;
base = ((Q)base * base) % MOD;
}
return ret;
}
MInt() : val(0) {}
MInt(P tv) : val(tv) {}
MInt operator+(const MInt &arg) const {
return MInt((val + (Q)arg.val) % MOD);
}
MInt operator-(const MInt &arg) const {
return MInt(((Q)val + MOD - (Q)arg.val) % MOD);
}
MInt operator*(const MInt &arg) const {
return MInt((val * (Q)arg.val) % MOD);
}
MInt operator/(const MInt &arg) const {
return MInt((val * (Q)selfPow(arg.val, MOD - 2)) % MOD);
}
MInt operator+(const P argv) const { return MInt((val * (Q)argv) % MOD); }
MInt operator-(const int argv) const {
return MInt(((Q)val + MOD - (Q)argv) % MOD);
}
MInt operator*(const int argv) const { return MInt((val * (Q)argv) % MOD); }
MInt operator/(const int argv) const {
return MInt((val * (Q)selfPow(argv, MOD - 2)) % MOD);
}
MInt &operator+=(const MInt &arg) {
this->val = ((Q)this->val + (Q)arg.val) % MOD;
return *this;
}
MInt &operator-=(const MInt &arg) {
this->val = ((Q)this->val + MOD - (Q)arg.val) % MOD;
return *this;
}
MInt &operator*=(const MInt &arg) {
this->val = ((Q)this->val * arg.val) % MOD;
return *this;
}
MInt &operator/=(const MInt &arg) {
this->val = ((Q)this->val * (Q)selfPow(arg.val, MOD - 2)) % MOD;
return *this;
}
MInt &operator+=(const int argv) {
this->val = ((Q)this->val + (Q)argv) % MOD;
return *this;
}
MInt &operator-=(const int argv) {
this->val = ((Q)this->val + MOD - (Q)argv) % MOD;
return *this;
}
MInt &operator*=(const int argv) {
this->val = ((Q)this->val * (Q)argv) % MOD;
return *this;
}
MInt &operator/=(const int argv) {
this->val = ((Q)this->val * (Q)selfPow(argv, MOD - 2)) % MOD;
return *this;
}
MInt &operator=(const MInt &arg) {
this->val = (Q)arg.val % MOD;
return *this;
}
MInt &operator=(const int argv) {
this->val = (Q)argv % MOD;
return *this;
}
bool operator==(const int argv) const { return (Q)val == (Q)argv; }
friend MInt operator+(const int argv, const MInt &arg) {
return MInt(((Q)arg.val + (Q)argv) % MOD);
}
friend MInt operator-(const int argv, const MInt &arg) {
return MInt(((Q)argv + MOD - (Q)arg.val) % MOD);
}
friend MInt operator*(const int argv, const MInt &arg) {
return MInt(((Q)arg.val * (Q)argv) % MOD);
}
friend MInt operator/(const int argv, const MInt &arg) {
return MInt(((Q)argv * (Q)MInt::selfPow(arg.val, MOD - 2)) % MOD);
}
friend istream &operator>>(istream &its, MInt &arg) {
its >> arg.val;
return its;
}
friend ostream &operator<<(ostream &ots, const MInt &arg) {
ots << arg.val;
return ots;
}
friend P abs(const MInt &arg) { return abs(arg.val); }
private:
P val;
};
素数筛¶
单个正整数判断是不是质数¶
bool isPrime(int x){
if(x <= 1) return false;
int cur = 2;
while(cur * cur <= x){
if(x % cur != 0){
return false;
}
++cur;
}
return true;
}
埃拉托斯特尼筛法¶
template<int N>
vector<int> SieveOfEratosthenes() {
vector<int> prime;
bitset<N + 1> notPrime;
notPrime[0] = notPrime[1] = 1;
for (int i = 2; i <= N; ++i) {
if (!notPrime[i]) {
prime.push_back(i);
if ((long long) i * i <= N) {
for (int j = i * i; j <= N; j += i) {
notPrime[j] = 1;
}
}
}
}
return prime;
}
线性筛(欧式筛)¶
template<int N>
vector<int> SieveOfEuler() {
vector<int> prime;
bitset<N + 1> notPrime;
for (int i = 2; i <= N; ++i) {
if (!notPrime[i]) {
prime.push_back(i);
}
for (auto it : prime) {
if ((long long) it * i <= N) {
notPrime[it * i] = 1;
if (i % it == 0) {
break;
}
}else{
break;
}
}
}
return prime;
}
奇数筛¶
template<int N>
vector<int> OddFilter() {
if (N < 2) return {};
vector<int> prime{2};
bitset<N + 1> notPrime;
notPrime[0] = notPrime[1] = 1;
for (int i = 3; i * i <= N; i += 2) {
if (!notPrime[i]) {
for (int j = i; j * i <= N; j += 2) {
notPrime[j * i] = 1;
}
}
}
for (int i = 3; i <= N; i += 2) {
if (!notPrime[i]) {
prime.push_back(i);
}
}
return prime;
}
类欧几里得算法¶
\[
f(N, a, b, c) = \sum_{i = 0}^N \lfloor \frac{a \times i + b}{c} \rfloor \\
g(N, a, b, c) = \sum_{i = 0}^N \lfloor \frac{a \times i + b}{c} \rfloor ^2 \\
h(N, a, b, c) = \sum_{i = 0}^N i \times \lfloor \frac{a \times i + b}{c} \rfloor
\]
##include <iostream>
##include <algorithm>
using namespace std;
const int MOD = 998244353;
int qPow(int b, int p){
int ret = 1;
while(p){
if(p & 1) ret = 1ll * ret * b % MOD;
b = 1ll * b * b % MOD;
p >>= 1;
}
return ret;
}
const int inv2 = qPow(2, MOD - 2);
const int inv6 = qPow(6, MOD - 2);
template<typename T>
tuple<T, T, T> euclidean(T n, T a, T b, T c){
T ac = a / c, bc = b / c, m = (a * n + b) / c, n1 = n + 1, n21 = n * 2 + 1;
if(a == 0){
return {
bc * n1 % MOD,
bc * n % MOD * n1 % MOD * inv2 % MOD,
bc * bc % MOD * n1 % MOD
};
}
if(a >= c or b >= c){
T f = n * n1 % MOD * inv2 % MOD * ac % MOD + bc * n1 % MOD;
T g = ac * n % MOD * n1 % MOD * n21 % MOD * inv6 % MOD + bc * n % MOD * n1 % MOD * inv2 % MOD;
T h = ac * ac % MOD * n % MOD * n1 % MOD * n21 % MOD * inv6 % MOD + bc * bc % MOD * n1 % MOD + ac * bc % MOD * n % MOD * n1 % MOD;
f %= MOD, g %= MOD, h %= MOD;
auto [tf, tg, th] = euclidean(n, a % c, b % c, c);
h += th + 2 * bc % MOD * tf % MOD + 2 * ac % MOD * tg % MOD;
g += tg;
f += tf;
return {f % MOD, g % MOD, h % MOD};
}
auto [tf, tg, th] = euclidean(m - 1, c, c - b - 1, a);
T f = (n * m % MOD + MOD - tf) % MOD;
T g = (n * m % MOD * n1 % MOD + MOD - th + MOD - tf) % MOD * inv2 % MOD;
T h = (n * m % MOD * (m + 1) % MOD + 2 * (MOD - tg) + 2 * (MOD - tf) + MOD - f) % MOD;
return {f, g, h};
}
typedef long long ll;
int main(){
int t;
cin >> t;
while(t--){
ll n, a, b, c;
cin >> n >> a >> b >> c;
auto [f, g, h] = euclidean(n, a, b, c);
cout << f << " " << h << " " << g << endl;
}
return 0;
}
拓展欧几里得¶
template<typename T>
T exgcd(T a, T b, T& x, T& y){
if(b == 0){
x = 1;
y = 0;
return a;
}
T d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
欧拉函数¶
单个欧拉函数¶
int euler_phi(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++)
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
批量求欧拉函数(线性筛)¶
vector<int> eularFunction(int n){
vector<int> isPrime(n + 1, 1), phi(n + 1, 0);
vector<int> prime;
int cnt = 0;
isPrime[1] = 0;
phi[1] = 1;
for(int i = 2; i <= n; ++i){
if(isPrime[i]){
prime.push_back(i);
phi[i] = i - 1;
}
for(auto it: prime){
if(i * it > n) break;
isPrime[i * it] = 0;
if(i % it){
phi[i * it] = phi[i] * phi[it];
}else{
phi[i * it] = phi[i] * it;
break;
}
}
}
return phi;
}
筛法求约数个数(线性筛)¶
vector<int> SieveOfEuler(int n){
vector<int> ret(n + 1, 0); //约数个数
vector<int> vis(n + 1, 0); //是否访问标记
vector<int> prime; // 质数表
vector<int> num(n + 1, 0); // 最小质数因子出现次数
ret[1] = 1;
for(int i = 2; i <= n; ++i){
if(!vis[i]){
vis[i] = 1;
prime.push_back(i);
ret[i] = 2;
num[i] = 1;
}
for(auto& it: prime){
if(n / it < i) break;
vis[it * i] = 1;
if(i % it == 0){
num[i * it] = num[i] + 1;
ret[i * it] = ret[i] / num[i * it] * (num[i * it] + 1);
break;
}else{
num[i * it] = 1;
ret[i * it] = ret[i] * 2;
}
}
}
return ret;
}
中国剩余定理 & 扩展中国剩余定理¶
template<typename T>
T exgcd(T a, T b, T& x, T& y){
if(b == 0){
x = 1, y = 0;
return a;
}
T d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
template<typename T>
T mul(T b, T n, T p){
T ans = 0;
while(n){
if(n & 1) ans = (ans + b % p) % p;
b = (b + b) % p;
n >>= 1;
}
return ans;
}
template<typename T>
T crt(vector<pair<T, T>>& args){
T M = 1, ans = 0, x, y;
for(auto& it: args) M *= it.first;
for(auto& it: args){
T b = M / it.first;
exgcd(it.first, b, x, y);
y = (y % it.first + it.first) % it.first;
ans = (ans + mul(mul(it.second, b, M), y, M)) % M;
}
return ans;
}
template<typename T>
bool excrt(pair<T, T>& res, vector<pair<T, T>>& args){
res = args.front();
for(int i = 1; i < args.size(); ++i){
T c = (args[i].second - res.second % args[i].first + args[i].first) % args[i].first;
T x, y;
T v = exgcd(res.first, args[i].first, x, y);
if(c % v) return false;
x = mul(x, c / v, args[i].first / v);
res.second = (res.second + x * res.first);
res.first *= args[i].first / v;
res.second = (res.second % res.first + res.first) % res.first;
}
return true;
}
乘法逆元¶
扩展欧几里得算法¶
template<typename T>
T exgcd(T a, T b, T& x, T& y){
if(b == 0){
x = 1, y = 0;
return a;
}
T d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
快速幂算法¶
template<typename T>
T qPow(T b, T n, T p){
T res = 1;
while(n){
if(n & 1) res = res * b % p;
b = b * b % p;
n >>= 1;
}
return res;
}
批量乘法逆元¶
MOD需要是质数
vector<int> reverse(int n, int MOD){
std::vector<int> inv(n + 1, 1);
for (int i = 2; i <= n; ++i) {
inv[i] = (long long) (MOD - MOD / i) * inv[MOD % i] % MOD;
}
return inv;
}
阶乘逆元(求组合数)¶
template<typename T = long long, int P = 1000000007>
class Combination{
public:
Combination(int n): div(n + 1, 1), mul(n + 1, 1){
for(int i = 1; i <= n; ++i) mul[i] = mul[i - 1] * i % P;
div[n] = qPow(mul[n], P - 2);
for(int i = n - 1; i > 0; --i) div[i] = div[i + 1] * (i + 1) % P;
}
T operator () (int n, int m){
if(m < 0) return 0;
if(m > n) return 0;
return mul[n] * div[m] % P * div[n - m] % P;
}
private:
T qPow(T b, T n){
T ret = 1;
while(n){
if(n & 1) ret = ret * b % P;
b = b * b % P;
n >>= 1;
}
return ret;
}
vector<T> div, mul;
};
卢卡斯定理¶
对于质数\(p\),有 $$ \binom{n}{m} \bmod p = \binom{\lfloor n / p \rfloor}{\lfloor m / p \rfloor} \cdot \binom{\lfloor n \bmod p \rfloor}{\lfloor m \bmod p \rfloor} \bmod p $$
template<typename T>
T lucas(T n, T m, T p, const function<T(T, T)>& C){
if(m == 0) return 1;
T c = C(n % p, m % p);
T res = (c * lucas(n / p, m / p, p, C)) % p;
return res;
}
BSGS¶
在\(a\)和\(p\)互质的情况下,求解 $$ a ^ x \equiv b \bmod p $$
template<typename T>
T qPow(T b, T n, T p){
T ret = 1;
while(n){
if(n & 1) ret = ret * b % p;
b = b * b % p;
n >>= 1;
}
return ret;
}
template<typename T>
T BSGS(T a, T b, T p, T c = 1){
map<T, T> mp;
T t = (T)sqrt(p) + 1;
b %= p;
ll tmp = 1;
for(int i = 0; i < t; ++i){
T tv = b * tmp % p;
mp[tv] = i;
tmp = (tmp * a) % p;
}
a = qPow(a, t, p);
if(a == 0) return b == 0 ? 1 : -1;
for(int i = 0; i <= t; ++i){
ll tv = qPow<T>(a, i, p) * c % p;
if(mp.count(tv) and i * t - mp[tv] >= 0){
return i * t - mp[tv];
}
}
return -1;
}
exBSGS¶
求解 $$ a ^ x \equiv b \bmod p $$
template<typename T>
T exgcd(T a, T b, T& x, T& y){
if(b == 0){
x = 1, y = 0;
return a;
}
T d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
template<typename T>
T qPow(T b, T n, T p){
T ret = 1;
while(n){
if(n & 1) ret = ret * b % p;
b = b * b % p;
n >>= 1;
}
return ret;
}
template<typename T>
T BSGS(T a, T b, T p, T c = 1){
map<T, T> mp;
T t = (T)sqrt(p) + 1;
b %= p;
ll tmp = 1;
for(int i = 0; i < t; ++i){
T tv = b * tmp % p;
mp[tv] = i;
tmp = (tmp * a) % p;
}
a = qPow(a, t, p);
if(a == 0) return b == 0 ? 1 : -1;
for(int i = 0; i <= t; ++i){
ll tv = qPow<T>(a, i, p) * c % p;
if(mp.count(tv) and i * t - mp[tv] >= 0){
return i * t - mp[tv];
}
}
return -1;
}
template<typename T>
T exBSGS(T a, T b, T p){
a %= p, b %= p;
if(b == 1 or p == 1) return 0;
T cnt = 0;
T d, ad = 1;
T na = 1;
while((d = gcd(a, p)) != 1){
if(b % d) return -1;
++cnt;
b /= d, p /= d;
ad = ad * (a / d) % p;
if(ad == b) return cnt;
}
T tx, ty;
T dv = exgcd<T>(ad, p, tx, ty);
tx = (tx % p + p) % p;
T ans = BSGS<T>(a, b * tx % p, p);
if(ans >= 0) ans += cnt;
return ans;
}
Cayley 公式(Caylay's formula)¶
完全图 \(K_n\) 有 \(n^{n - 2}\) 棵生成树。
莫比乌斯函数(线性筛)¶
template<int N, typename T = int>
class Mu {
public:
Mu() : muArr(N + 1), pref(N + 1) {
bitset<N + 1> notPrime;
muArr[1] = 1;
for (int i = 2; i <= N; ++i) {
if (!notPrime[i]) {
prime.push_back(i);
muArr[i] = -1;
}
for (auto it : prime) {
if (N / i >= it) {
notPrime[it * i] = 1;
if (i % it == 0) {
break;
} else {
muArr[i * it] = -muArr[i];
}
} else {
break;
}
}
}
pref[0] = 0;
for (int i = 1; i <= N; ++i) {
pref[i] = pref[i - 1] + muArr[i];
}
}
T& operator[](int i) {
return muArr[i];
}
vector<T> pref;
vector<T> prime;
private:
vector<T> muArr;
};
杜教筛¶
template<int N = 5000000>
struct Du{
Du(): vis(N + 1, 0), mu(N + 1, 0), musum(N + 1, 0) {
mu[1] = 1;
for(int i = 2; i <= N; ++i){
if(!vis[i]){
pri.push_back(i);
mu[i] = -1;
}
for(auto& it: pri){
if(1ll * i * it > N) break;
vis[i * it] = 1;
if(i % it){
mu[i * it] = - mu[i];
}else{
mu[i * it] = 0;
break;
}
}
}
for(int i = 1; i <= N; ++i) musum[i] = musum[i - 1] + mu[i];
}
long long getMuSum(int x){
if(x <= N) return musum[x];
if(lazyMu.count(x)) return lazyMu[x];
long long ret = 1;
for(long long i = 2, j; i <= x; i = j + 1){
j = x / (x / i);
ret -= getMuSum(x / i) * (j - i + 1);
}
return lazyMu[x] = ret;
}
long long getPhiSum(int x){
long long ret = 0;
for(long long i = 1, j; i <= x; i = j + 1){
j = x / (x / i);
ret += (getMuSum(j) - getMuSum(i - 1)) * (x / i) * (x / i);
}
return (ret - 1) / 2 + 1;
}
map<int, long long> lazyMu;
vector<int> mu, musum, pri;
vector<bool> vis;
};
康拓展开¶
正向¶
/**
* @brief 康拓展开
* @param t 排列,这里设定排列的长度是9
* @return Contar值
* @author dianhsu
**/
int radix[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
template<int LEN=9>
int Contar(int* t){
int ret = 0;
for(int i = 0; i < LEN; ++i){
int tmp = 0;
for(int j = i + 1; j < LEN; ++j){
if(t[i] > t[j]){
++tmp;
}
}
ret += radix[LEN - 1 - i] * tmp;
}
return ret;
}
反向¶
/**
* @brief 康拓展开的逆运算
* @param contar_val Contar 值
* @param t 返回的Contar序列
* @author dianhsu
* */
int radix[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
template<int LEN=9>
void ReverseContar(int contar_val, int* t){
int vis[LEN];
memset(vis, 0, sizeof vis);
for(int i = 0; i < LEN; ++i){
int idx = contar_val / radix[LEN - 1 - i];
contar_val = contar_val % radix[LEN - 1 - i];
for(int j = 0; j < LEN; ++j){
if(vis[j] == 0){
if(idx == 0){
vis[j] = 1;
t[i] = j;
break;
}else{
--idx;
}
}
}
}
}
Miller Rabin & Pollard Rho¶
random_device rd;
mt19937_64 gen(rd());
uniform_int_distribution<ll> dis(0);
ll qPow(ll b, ll p, ll mod){
ll ret = 1;
while(p){
if(p & 1) ret = (__int128)ret * b % mod;
b = (__int128)b * b % mod;
p >>= 1;
}
return ret;
}
bool MillerRabin(ll p){
if(p < 2) return false;
if(p < 4) return true;
ll d = p - 1;
int r = 0;
while((d & 1) == 0) ++r, d >>= 1;
for(ll k = 0; k < 10; ++k){
ll rv = dis(gen) % (p - 2) + 2;
ll x = qPow(rv, d, p);
if(x == 1 or x == p - 1) continue;
for(int i = 0; i < r - 1; ++i){
x = (__int128) x * x % p;
if(x == p - 1) break;
}
if(x != p - 1) return false;
}
return true;
}
ll PollardRho(ll n){
ll c = rand() % (n - 1) + 1;
ll s = 0, t = 0;
for(ll goal = 1, val = 1; ; goal *= 2, s = t, val = 1){
for(ll step = 1; step <= goal; ++step){
t = ((__int128) t * t + c) % n;
val = (__int128)val * abs(t - s) % n;
if(step % 127 == 0){
ll d = gcd(val, n);
if(d > 1) return d;
}
}
ll d = gcd(val, n);
if(d > 1) return d;
}
}
线性代数¶
矩阵¶
矩阵模板,搭配模数可以当成矩阵快速幂。
template<typename T>
struct Matrix{
std::vector<T> data;
int sz;
// 构造全0矩阵,或者斜对角填上自定义数字
Matrix(int sz, T v = 0): sz(sz), data(sz * sz, 0){
int cur = 0;
do{
data[cur] = v;
cur += sz + 1;
}while(cur < sz * sz);
}
//从vector中构造矩阵
Matrix(int sz, std::vector<T>& arg): sz(sz), data(sz * sz, 0){
assert(arg.size() >= sz * sz);
for(int i = 0; i < sz * sz; ++i) data[i] = arg[i];
}
//从vector中构造矩阵,右值
Matrix(int sz, std::vector<T>&& arg): sz(sz), data(sz * sz, 0){
assert(arg.size() >= sz * sz);
for(int i = 0; i < sz * sz; ++i) data[i] = arg[i];
}
Matrix operator + (const Matrix& arg) const {
assert(sz == arg.sz);
Matrix ret(sz);
for(int i = 0; i < sz * sz; ++i){
ret.data[i] = data[i] + arg.data[i];
}
return ret;
}
Matrix operator * (const Matrix& arg) const {
assert(sz == arg.sz);
Matrix ret(sz);
for(int i = 0; i < sz; ++i){
for(int j = 0; j < sz; ++j){
for(int k = 0; k < sz; ++k){
ret.data[i * sz + j] += data[i * sz + k] * arg.data[k * sz + j];
}
}
}
return ret;
}
Matrix operator - (const Matrix& arg) const {
assert(sz == arg.sz);
Matrix ret(sz);
for(int i = 0; i < sz * sz; ++i) ret.data[i] = data[i] - arg.data[i];
return ret;
}
friend std::ostream & operator << (std::ostream& ots, const Matrix& arg){
for(int i = 0; i < arg.sz; ++i){
for(int j = 0; j < arg.sz; ++j){
if(j) ots << " ";
ots << arg.data[i * arg.sz + j];
}
if(i + 1 != arg.sz) ots << "\n";
}
return ots;
}
};
高斯消元¶
template<typename T>
struct Gauss{
Gauss(int argR, int argC): r(argR), c(argC), mat(r, vector<T>(c, 0)), idx(r, 0){
assert(argC >= argR);
iota(idx.begin(), idx.end(), 0);
}
T& operator () (int row, int col){
return mat[row][col];
}
int r, c;
friend istream& operator >> (istream& its, Gauss& arg){
for(int i = 0; i < arg.r; ++i){
for(int j = 0; j < arg.c; ++j){
its >> arg(i, j);
}
}
return its;
}
friend ostream& operator << (ostream& ots, Gauss& arg){
for(int i = 0; i < arg.r; ++i){
for(int j = 0; j < arg.c; ++j){
ots << arg(arg.idx[i], j);
if(j + 1 != arg.c) ots << " ";
}
if(i + 1 != arg.r) ots << "\n";
}
return ots;
}
vector<vector<T>> mat;
vector<int> idx;
bool elimination(const function<bool(T)>& isZero, const function<T(T)>& inv){
for(int i = 0; i < r; ++i){
int cur = i;
for(int j = i + 1; j < r; ++j){
if(abs(mat[idx[j]][i]) > abs(mat[idx[cur]][i])){
cur = j;
}
}
swap(idx[i], idx[cur]);
if(isZero(mat[idx[i]][i])) return false;
T mul = inv(mat[idx[i]][i]);
for(int j = i; j < c; ++j){
mat[idx[i]][j] *= mul;
}
for(int i1 = 0; i1 < r; ++i1){
if(i1 == i) continue;
T cmul = mat[idx[i1]][i];
for(int j = i; j < c; ++j){
mat[idx[i1]][j] -= mat[idx[i]][j] * cmul;
}
}
}
return true;
}
};
线性基¶
struct LBase{
vector<long long> _data;
LBase(): _data(64, 0){}
bool insert(long long x){
for(int i = 63 - __builtin_clzll(x); i >= 0; --i){
if((x >> i) & 1){
if(_data[i]) x ^= _data[i];
else{
_data[i] = x;
break;
}
}
}
return x > 0;
}
LBase& operator += (const LBase& arg){
for(auto ptr = arg._data.rbegin(); ptr != arg._data.rend(); ++ptr){
this->insert(*ptr);
}
return *this;
}
long long query(){
long long ret = 0;
for(auto ptr = _data.rbegin(); ptr != _data.rend(); ++ptr){
if(*ptr){
if((ret ^ (*ptr)) > ret) ret ^= *ptr;
}
}
return ret;
}
int count(){
int ret = 0;
for(auto& it: _data) if(it) ++ret;
return ret;
}
};
自适应辛普森¶
template<typename T>
T simpson(T l, T r, const function<T(T)>& f){
T mid = (l + r) / 2;
return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;
}
template<typename T>
T asr(T l, T r, T delta, T ans, int step, const function<T(T)>& f){
T mid = (l + r) / 2;
T fl = simpson<T>(l, mid, f), fr = simpson<T>(mid, r, f);
if(abs(fl + fr - ans) <= 15 * delta and step < 0){
return fl + fr + (fl + fr - ans) / 15;
}
return asr(l, mid, delta / 2, fl, step - 1, f) + asr(mid, r, delta / 2, fr, step - 1, f);
}
template<typename T = double>
T adaptiveSimpson(T l, T r, T delta, const function<T(T)>& f){
return asr<T>(l, r, delta, simpson<T>(l, r, f), 12, f);
}
多项式¶
快速傅立叶变换¶
template<typename T>
void butterflyDiagram(vector<complex<T>>& vec){
assert(__builtin_popcount(vec.size()) == 1);
vector<int> rev(vec.size());
for(int i = 0; i < vec.size(); ++i){
rev[i] = rev[i >> 1] >> 1;
if(i & 1){
rev[i] |= (vec.size() >> 1);
}
}
for(int i = 0; i < vec.size(); ++i){
if(i < rev[i]){
swap(vec[i], vec[rev[i]]);
}
}
}
// on == 1 时是 DFT,on == -1 时是 IDFT
template<typename T>
void fft(vector<complex<T>>& vec, int on){
assert(__builtin_popcount(vec.size()) == 1);
butterflyDiagram(vec);
for(int h = 1; h < vec.size(); h <<= 1){
complex<T> wn(cos(M_PI / h), sin(on * M_PI / h));
for(int j = 0; j < vec.size(); j += h * 2){
complex<T> w(1, 0);
for(int k = j; k < j + h; ++k){
assert(k < vec.size() and h + k < vec.size());
auto u = vec[k];
auto t = w * vec[k + h];
vec[k] = u + t;
vec[k + h] = u - t;
w *= wn;
}
}
}
if(on == -1){
for(auto& it: vec){
it.real(it.real() / vec.size());
}
}
}