您的位置:首页 > 其它

数学基础II 线性基 高斯消元 中国剩余定理 BSGS

2018-02-05 22:04 375 查看

线性基

线性基可以“存储”一个数的集合的所有子集的异或和。它支持查询最大/最小/第k小子集异或和或一个异或和是否存在。线性基可以插入,但不能删除。

long long a[55], s[55], top;

void insert(long long x) {
for(int i = 62; i >= 0; i--) if(x&(1ll<<i)) {
if(!a[i]) {
a[i] = x;
return;
}
x ^= a[i];
}
}

int exist(long long x) {
for(int i = 62; i >= 0; i--) if(x&(1ll<<i)) {
x ^= a[i];
if(!x) return 1;
}
return 0;
}

long long query_max() {
long long ans = 0;
for(int i = 62; i >= 0; i--) if((ans^a[i]) > ans) ans ^= a[i];
return ans;
}

long long query_min() {
for(int i = 0; i <= 62; i++) if(a[i]) return a[i];
return -1;
}

long long kth(int k) {
for(int i = 62; i >= 0; i--) for(int j = i-1; j >= 0; j--) if(a[i]&(1ll<<j)) a[i] ^= a[j];
top = 0;
for(int i = 0; i <= 62; i++) if(a[i]) s[top++] = a[i];
long long ans = 0;
for(int i = 62; i >= 0; i--) if(k&(1ll<<i)) ans ^= a[i];
return ans;
}


矩阵

高斯消元

几乎就是手动消元的过程。

void gauss() {
for(int i = 0; i < n; i++) {
int r = i;
for(int j = i+1; j < n; j++) if(fabs(a[j][i]) > fabs(a[r][i])) r = j;
for(int j = 0; j <= n; j++) swap(a[i][j], a[r][j]);
for(int j = n; j >= i; j--) for(int k = i+1; k < n; k++) a[k][j] -= a[k][i]/a[i][i] * a[i][j]; // 提高精度
}
for(int i
14c99
= n-1; i >= 0; i--) { // 回代
for(int j = i+1; j < n; j++) a[i]
-= a[j]
* a[i][j];
a[i]
/= a[i][i];
}
}


矩阵的逆

用高斯消元。

中国剩余定理

中国剩余定理用于求解形如x≡bi(modmi)x≡bi(modmi)的一组方程。

设有nn个方程,我们计算另外“特殊的”nn个方程组的解。第pp个“特殊方程组”形如x≡bp(modmp)x≡bp(modmp);x≡bi(modmi),i≠px≡bi(modmi),i≠p。

可以轻易地用扩展欧几里得求出这些“特殊方程组”的解。

则原方程组的解,就等于每一组“特殊方程组”的解乘以其序号对应的系数的和,对∏ni=1mi∏i=1nmi取模。

int china() {
int M = 1, ans = 0;
for(int i = 0; i < n; i++) M *= m[i];
for(int i = 0; i < n; i++) {
int d, y;
exgcd(m[i], M/m[i], d, d, y);
ans = (ans + y*(M/m[i])*a[i]) % M;
}
return ans;
}


大步小步算法

大步小步算法用于解方程ax≡b(modn)ax≡b(modn),时间复杂度为O(n−−√)O(n)。

根据欧拉定理,如果有解,则解一定在[0,n)[0,n)中。

BSGS的基本思想是先求出ei=aimodn(i<n−−√)ei=aimodn(i<n),全部存在哈希表中。对于之后的ii,只需检查是否有ei=a−jmb(0<j<n−−√)ei=a−jmb(0<j<n)即可。

这体现了一种分组的思想。

Miller-Rabin素数测试

Miller-Rabin算法是基于费马小定理的。

这个Miller_Rabin没有用二次探测定理,但不保证会出错。

int miller_rabin(int x) {
if(x == 2) return 1;
for(int i = 0; i < 10; i++) {
int a = rand() % (x-2) + 2;
if(qpow(a, x, x) != a) return 0;
}
return 1;
}


Pollard Rho

明天
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: