zoukankan      html  css  js  c++  java
  • 特辑:卡特兰数 & Prufer & BSGS

    总共9道题怎么显示我A了10道(

    Part 1: 卡特兰数:

    Problem A:网格

    不是卡特兰数,但推导过程类似。

    首先A到B总步数为曼哈顿距离 $ m + n $ .于是总方案数为 $ C_{m + n} ^ m $.

    考虑非法的情况,把所有跨越那条分界线的路径沿恰好跨过的那条线翻折,等价于从 ((0, 0))((m - 1, n + 1)),非法方案数为 $ C_{m + n} ^ {m - 1} $。

    数太大啦,用质因数分解 + BigInt 求。

    BigInt 真好用 x1

    #include <bits/stdc++.h>
    
    int n, m, mip[10005], pri[10005], cnt[10005][10005], fin[10005];
    
    void init(int t) {
    	for (int i = 2; i <= t; i++) {
    		if (!mip[i]) mip[i] = i, pri[++pri[0]] = i;
    		for (int j = 1; j <= pri[0] && i * pri[j] <= t; j++) {
    			mip[i * pri[j]] = pri[j];
    			if (i % pri[j] == 0) break;
    		}
    	}
    	for (int i = 2; i <= t; i++) {
    		for (int j = 1; j <= pri[0]; j++) {
    			int x = i;
    			while (x % pri[j] == 0) ++cnt[i][j], x /= pri[j];
    			cnt[i][j] += cnt[i - 1][j];
    		}
    	}
    }
    
    struct BigInt {
    	int l, a[23333], base;
    	BigInt() {
    		l = 0, base = 10;
    		memset(a, 0, sizeof(a));
    	}
    	BigInt Trans(int x) {
    		BigInt y;
    		while (x)
    			y.a[++y.l] = x % y.base, x /= y.base;
    		return y;
    	}
    	friend BigInt operator +(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = std::max(x.l, y.l);
    		for (int i = 1; i <= z.l; i++)
    			z.a[i] = x.a[i] + y.a[i], z.a[i + 1] += z.a[i] / x.base, x.a[i] %= x.base;
    		if (z.a[z.l + 1]) z.l++;
    		return z;
    	}
    	friend BigInt operator +(BigInt x, int y) {
    		BigInt tmp = tmp.Trans(y);
    		return x + tmp;
    	}
    	friend BigInt operator -(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = std::max(x.l, y.l);
    		for (int i = 1; i <= z.l; i++) {
    			if (x.a[i] < y.a[i]) x.a[i] += x.base, x.a[i + 1]--;
    			z.a[i] = x.a[i] - y.a[i];
    		}
    		while (!z.a[z.l] && z.l) z.l--;
    		if (z.l == 0) z.a[1] = 1, z.l = 1;
    		return z;
    	}
    	friend BigInt operator *(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = x.l + y.l;
    		if ((x.l == 1 && x.a[1] == 0) || (y.l == 1 && y.a[1] == 0)) {
    			z.l = 1;
    			return z;
    		}
    		for (int i = 1; i <= x.l; i++)
    			for (int j = 1; j <= y.l; j++)
    				z.a[i + j - 1] += x.a[i] * y.a[j], z.a[i + j] += z.a[i + j - 1] / x.base, z.a[i + j - 1] %= x.base;
    		while (!z.a[z.l] && z.l) z.l--;
    		if (!z.l) {z.l = 1, z.a[1] = 0;}
    		return z;
    	}
    	friend BigInt operator *(BigInt x, int y) {
    		BigInt z; int l = x.l;
    		for (int i = 1; i <= l; i++)
    			z.a[i] += x.a[i] * y, z.a[i + 1] += z.a[i] / x.base, z.a[i] %= x.base;
    		while (z.a[l + 1])
    			l++, z.a[l + 1] += z.a[l] / x.base, z.a[l] %= x.base;
    		z.l = l;
    		while (!z.a[z.l]) z.l--;
    		return z;
    	}
    	friend BigInt operator /(BigInt x, int y) {
    		BigInt z; z.l = x.l;
    		int t = 0;
    		for (int i = x.l; i >= 1; i--)
    			t = t * 10 + x.a[i], z.a[i] = t / y, t %= y;
    		while (!z.a[z.l]) z.l--;
    		return z;
    	}
    	void print() {
    		for (int i = l; i >= 1; i--)
    			printf("%d", a[i]);
    		printf("
    ");
    	}
    };
    
    BigInt Qpow(int x, int p) {
    	BigInt ret = ret.Trans(1), tmp = tmp.Trans(x);
    	for (; p; p >>= 1, tmp = tmp * tmp)
    		if (p & 1) ret = ret * tmp;
    	return ret;
    }
    
    signed main() {
    	scanf("%d%d", &n, &m);
    	init(n+ m);
    	for (int i = 1; i <= pri[0]; i++)
    		fin[i] = cnt[n + m][i] + cnt[n - m + 1][i] - cnt[n - m][i] - cnt[m][i] - cnt[n + 1][i];
    	BigInt ans; ans.l = 1, ans.a[1] = 1;
    	for (int i = 1; i <= pri[0]; i++)
    		ans = ans * Qpow(pri[i], fin[i]);
    	ans.print();
    	return 0;
    }
    

    Problem B: 有趣的数列

    和出栈入栈没区别,裸卡特兰数。

    数太大啦,用质因数分解

    能取模,不用BigInt了(

    #include <bits/stdc++.h>
    #define ll long long
    
    ll ans = 1;
    int n, p, pri[10000005], mip[10000005], cnt[10000005];
    
    ll Qpow(int x, int b, int p) {
    	ll ret = 1;
    	for (; b; b >>= 1, x = x * x % p)
    		if (b & 1) ret = ret * x % p;
    	return ret;
    }
    
    signed main() {
    	scanf("%d%d", &n, &p);
    	for (int i = 2; i <= n; i++) cnt[i] = -1;
    	for (int i = n + 2; i <= 2 * n; i++) cnt[i] = 1;
    	for (int i = 2; i <= 2 * n; i++) {
    		if (!mip[i]) mip[i] = i, pri[++pri[0]] = i;
    		for (int j = 1; j <= pri[0] && pri[j] * i <= 2 * n; j++) {
    			mip[pri[j] * i] = pri[j];
    			if (i % pri[j] == 0) break;
    		} 
    	}
    	for (int i = 2 * n; i >= 2; i--) {
    		if (mip[i] != i) {
    			cnt[mip[i]] += cnt[i];
    			cnt[i / mip[i]] += cnt[i];
    		} else ans = (ans * Qpow(i, cnt[i], p)) % p;
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    Problem C: 树屋阶梯

    没那么裸的卡特兰数

    n阶阶梯分成n块,那么每一块必定包含一个"突起"。

    而我们关注包含左下角底角那块,它的宽度可能为1 - n.而它可以把阶梯分成0阶和n-1阶,1阶和n-2阶.....

    最后答案为:(f(n) = f(0)f(n-1) + f(1)(n-2) + ...),这玩意就是卡特兰数。

    数太大啦,用质因...

    不用,用递推的那个卡特兰数公式(

    然而还是要BigInt

    BigInt 真好用 x2

    #include <bits/stdc++.h>
    
    int n;
    
    struct BigInt {
    	int l, a[2333], base;
    	BigInt() {
    		l = 0, base = 10;
    		memset(a, 0, sizeof(a));
    	}
    	friend BigInt operator +(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = std::max(x.l, y.l);
    		for (int i = 1; i <= z.l; i++)
    			z.a[i] = x.a[i] + y.a[i], z.a[i + 1] += z.a[i] / x.base, x.a[i] %= x.base;
    		if (z.a[z.l + 1]) z.l++;
    		return z;
    	}
    	friend BigInt operator -(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = std::max(x.l, y.l);
    		for (int i = 1; i <= z.l; i++) {
    			if (x.a[i] < y.a[i]) x.a[i] += x.base, x.a[i + 1]--;
    			z.a[i] = x.a[i] - y.a[i];
    		}
    		while (!z.a[z.l] && z.l) z.l--;
    		if (z.l == 0) z.a[1] = 1, z.l = 1;
    		return z;
    	}
    	friend BigInt operator *(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = x.l + y.l;
    		if ((x.l == 1 && x.a[1] == 0) || (y.l == 1 && y.a[1] == 0)) {
    			z.l = 1, z.a[1] = 0;
    			return z;
    		}
    		for (int i = 1; i <= x.l; i++)
    			for (int j = 1; j <= y.l; j++)
    				z.a[i + j - 1] += x.a[i] * y.a[j], z.a[i + j] += z.a[i + j - 1] / x.base, z.a[i + j - 1] %= x.base;
    		if (z.a[z.l + 1]) z.l++;
    		return z;
    	}
    	friend BigInt operator *(BigInt x, int y) {
    		BigInt z; int l = x.l;
    		for (int i = 1; i <= l; i++)
    			z.a[i] += x.a[i] * y, z.a[i + 1] += z.a[i] / x.base, z.a[i] %= x.base;
    		while (z.a[l + 1])
    			l++, z.a[l + 1] += z.a[l] / x.base, z.a[l] %= x.base;
    		z.l = l;
    		return z;
    	}
    	friend BigInt operator /(BigInt x, int y) {
    		BigInt z; z.l = x.l;
    		int t = 0;
    		for (int i = x.l; i >= 1; i--)
    			t = t * 10 + x.a[i], z.a[i] = t / y, t %= y;
    		while (!z.a[z.l]) z.l--;
    		return z;
    	}
    	void print() {
    		for (int i = l; i >= 1; i--)
    			printf("%d", a[i]);
    		printf("
    ");
    	}
    };
    
    signed main() {
    	scanf("%d", &n);
    	BigInt Cat[505];
    	Cat[1].l = 1, Cat[1].a[1] = 1;
    	for (int i = 2; i <= n; i++)
    		Cat[i] = Cat[i - 1] * (4 * i - 2) / (i + 1);
    	Cat[n].print();
    	return 0;
    }
    

    Part 2: Prufer序列

    Problem D: 树的计数

    根据Prufer序列的性质,树节点数为n,Prufer序列长为n - 2,每个点出现度数-1次。

    所以数的种数为(C_{n - 2} ^ {d_1 - 1} C_{n - 2 - (d_1 - 1)} ^ {d_2 - 1} ...) ,化简得:(frac{(n - 2) !}{prod limits_{i = 1}^{n}(d_i - 1)!}).

    数不大了,不用BigInt啦

    但分解质因数还是要的(

    #include <bits/stdc++.h>
    #define ll long long
    
    int n, d[155], sum, pri[500], mip[500], cnt[500][500], ans[500];
    ll QAQ;
    
    ll Qpow(int x, int b) {
    	ll ret = 1;
    	for (; b; b >>= 1, x *= x)
    		if (b & 1) ret *= x;
    	return ret;
    }
    
    signed main() {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", d + i);
    		if (d[i] == 0 && n > 1) {
    			puts("0");
    			return 0;
    		}
    		sum += d[i] - 1;
    	}
    	if (sum != n - 2) {
    		puts("0");
    		return 0;
    	}
    	for (int i = 2; i <= n; i++) {
    		if (mip[i] != i) mip[i] = i, pri[++pri[0]] = i;
    		for (int j = 1; j <= pri[0] && i * pri[j] <= n; j++) {
    			mip[i * pri[j]] = pri[j];
    			if (i % pri[j] == 0) break;
    		}
    	}
    	for (int i = 2; i <= n; i++) {
    		for (int j = 1; j <= pri[0]; j++) {
    			cnt[i][j] = 0;
    			int x = i;
    			while (x % pri[j] == 0) cnt[i][j]++, x /= pri[j];
    			cnt[i][j] += cnt[i - 1][j];
    		}
    	}
    	for (int i = 1; i <= pri[0]; i++) ans[i] = cnt[n - 2][i];
    	QAQ = 1;
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= pri[0]; j++)
    			ans[j] -= cnt[d[i] - 1][j];
    	for (int i = 1; i <= pri[0]; i++)
    		QAQ = QAQ * Qpow(pri[i], ans[i]);
    	printf("%lld
    ", QAQ);
    	return 0;
    }
    

    Problem E: 明明的烦恼

    首先给出度数k个点,当前Prufer序列总长(sum = sum limits_{i = 1} ^ k (d_i - 1)), 它对答案贡献为 (C_{n - 2} ^ {sum} frac{sum!}{prod limits_{i = 1}^k (d_i - 1)!}).

    剩下的点填满 $ n - sum - 2 $ 个空位,贡献为 $ (n - k) ^ {n - sum - 2} $.

    最终答案:$ C_{n - 2} ^ {sum} frac{sum!}{prod limits_{i = 1}^k (d_i - 1)!} (n - k) ^ {n - sum - 2} $.

    化简:(frac{(n - 2)!}{ (n - sum - 2)! prod limits_{i = 1}^k (d_i - 1)!} (n - k) ^ {n - sum - 2})

    数太大啦,用质因数分解 + BigInt 求。

    BigInt 真好用 x3

    #include <bits/stdc++.h>
    
    int n, d[1005], QAQ, pri[1005], mip[1005], cnt[1005][1005], fin[1005], sum;
    
    void init(int t) {
    	for (int i = 2; i <= t; i++) {
    		if (!mip[i]) mip[i] = i, pri[++pri[0]] = i;
    		for (int j = 1; j <= pri[0] && i * pri[j] <= t; j++) {
    			mip[i * pri[j]] = pri[j];
    			if (i % pri[j] == 0) break;
    		}
    	}
    	for (int i = 2; i <= t; i++) {
    		for (int j = 1; j <= pri[0]; j++) {
    			int x = i;
    			while (x % pri[j] == 0) ++cnt[i][j], x /= pri[j];
    			cnt[i][j] += cnt[i - 1][j];
    		}
    	}
    }
    
    struct BigInt {
    	int l, a[23333], base;
    	BigInt() {
    		l = 0, base = 10;
    		memset(a, 0, sizeof(a));
    	}
    	BigInt Trans(int x) {
    		BigInt y;
    		while (x)
    			y.a[++y.l] = x % y.base, x /= y.base;
    		return y;
    	}
    	friend BigInt operator +(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = std::max(x.l, y.l);
    		for (int i = 1; i <= z.l; i++)
    			z.a[i] = x.a[i] + y.a[i], z.a[i + 1] += z.a[i] / x.base, x.a[i] %= x.base;
    		if (z.a[z.l + 1]) z.l++;
    		return z;
    	}
    	friend BigInt operator +(BigInt x, int y) {
    		BigInt tmp = tmp.Trans(y);
    		return x + tmp;
    	}
    	friend BigInt operator -(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = std::max(x.l, y.l);
    		for (int i = 1; i <= z.l; i++) {
    			if (x.a[i] < y.a[i]) x.a[i] += x.base, x.a[i + 1]--;
    			z.a[i] = x.a[i] - y.a[i];
    		}
    		while (!z.a[z.l] && z.l) z.l--;
    		if (z.l == 0) z.a[1] = 1, z.l = 1;
    		return z;
    	}
    	friend BigInt operator *(BigInt x, BigInt y) {
    		BigInt z;
    		z.l = x.l + y.l;
    		if ((x.l == 1 && x.a[1] == 0) || (y.l == 1 && y.a[1] == 0)) {
    			z.l = 1;
    			return z;
    		}
    		for (int i = 1; i <= x.l; i++)
    			for (int j = 1; j <= y.l; j++)
    				z.a[i + j - 1] += x.a[i] * y.a[j], z.a[i + j] += z.a[i + j - 1] / x.base, z.a[i + j - 1] %= x.base;
    		while (!z.a[z.l] && z.l) z.l--;
    		if (!z.l) {z.l = 1, z.a[1] = 0;}
    		return z;
    	}
    	friend BigInt operator *(BigInt x, int y) {
    		BigInt z; int l = x.l;
    		for (int i = 1; i <= l; i++)
    			z.a[i] += x.a[i] * y, z.a[i + 1] += z.a[i] / x.base, z.a[i] %= x.base;
    		while (z.a[l + 1])
    			l++, z.a[l + 1] += z.a[l] / x.base, z.a[l] %= x.base;
    		z.l = l;
    		while (!z.a[z.l]) z.l--;
    		return z;
    	}
    	friend BigInt operator /(BigInt x, int y) {
    		BigInt z; z.l = x.l;
    		int t = 0;
    		for (int i = x.l; i >= 1; i--)
    			t = t * 10 + x.a[i], z.a[i] = t / y, t %= y;
    		while (!z.a[z.l]) z.l--;
    		return z;
    	}
    	void print() {
    		for (int i = l; i >= 1; i--)
    			printf("%d", a[i]);
    		printf("
    ");
    	}
    };
    
    BigInt Qpow(int x, int p) {
    	BigInt ret = ret.Trans(1), tmp = tmp.Trans(x);
    	for (; p; p >>= 1, tmp = tmp * tmp)
    		if (p & 1) ret = ret * tmp;
    	return ret;
    }
    
    signed main() {
    	scanf("%d", &n);
    	init(1000);
    	for (int i = 1, x; i <= n; i++) {
    		scanf("%d", &x);
    		if (x != -1) d[++QAQ] = x, sum += x - 1;
    	}
    	BigInt ans = ans.Trans(1);
    	ans = ans * Qpow(n - QAQ, n - 2 - sum);
    	for (int i = 1; i <= pri[0]; i++) {
    		fin[i] += cnt[n - 2][i] - cnt[n - sum - 2][i];
    		for (int j = 1; j <= QAQ; j++)
    			fin[i] -= cnt[d[j] - 1][i];
    	}
    	for (int i = 1; i <= pri[0]; i++)
    		ans = ans * Qpow(pri[i], fin[i]);
    	ans.print();
    	return 0;
    }
    

    Part 3: BSGS 百事公司

    Problem F: 随机数生成器

    数列神题(

    (x_{i+1} = (ax_i + b) mod p),使用构造法,(x_{i + 1} + lambda = a(x_i + lambda) mod p).

    解得:(lambda = frac{b}{a - 1}).

    则数列({x_i})通项公式为(x_i = (x_1 + frac{b}{a - 1}) a^{i - 1}).

    (x_i = t)时,((x_1 + frac{b}{a - 1}) a^{i - 1} = t),即:(a_{i - 1} equiv t imes (x_1 + frac{b}{a - 1}) ^ {-1} mod p).

    这是BSGS的形式,根据这玩意解就万事了。

    关于BSGS 拔山盖世,它用于求解 (a^x equiv b mod p) 这样的同余方程。

    主要思路:把 (x) 拆成 (i * m - j), (a^{i * m} equiv b * a ^ {j} mod p).

    从0 - m 枚举j算出右式的值塞到Hash Table,由于拆成减的形式,j越大越优。

    最后枚举i,求左式,在Hash Table找对应值,找到就是答案,最后找不到无解。

    因为我很懒,天天用map

    #include <bits/stdc++.h>
    
    long long p, a, b, x_1, t, T, tt;
    
    long long Qpow(long long x, long long y, long long p) {
    	long long ret = 1;
    	for (; y; y >>= 1, x = x * x % p)
    		if (y & 1) ret = ret * x % p;
    	return ret;
    }
    
    long long BSGS(long long x, long long y, long long p) {
    	long long m = ceil(sqrt(p)), t = 1;
    	std::map<long long, long long> hash;
    	for (int i = 0; i <= m; i++, y = y * x % p) hash[y] = i;
    	long long f = Qpow(a, m, p);
    	for (int i = 1; i <= m; i++) {
    		t = t * f % p;
    		if (hash.count(t)) return i * m - hash[t] + 1;
    	}
    	return -1;
    }
    
    signed main() {
    	scanf("%lld", &T);
    	while (T--) {
    		scanf("%lld%lld%lld%lld%lld", &p, &a, &b, &x_1, &t);
    		if (x_1 == t) {puts("1"); continue;}
    		if (a == 0) {puts(b == t ? "2" : "-1"); continue;}
    		if (a == 1) {
    			if (b == 0) {puts("-1"); continue;}
    			long long c = Qpow(b, p - 2, p) % p, d = (t - x_1 + p) % p;
    			printf("%lld
    ", d * c % p + 1);
    			continue;
    		}
    		long long u = b * Qpow(a - 1, p - 2, p) % p;
    		tt = ((t + u) * Qpow((x_1 + u) % p, p - 2, p)) % p;
    		printf("%lld
    ", BSGS(a, tt, p));
    	}
    	return 0;
    }
    

    Problem G: 计算器

    模板三合一,不说了,秒了

    #include <bits/stdc++.h>
    #define ll long long
    
    int T, opt;
    ll y, z, p;
    
    ll Qpow(ll x, int b, ll p) {
    	ll ret = 1;
    	for (; b; b >>= 1, x = x * x % p)
    		if (b & 1) ret = ret * x % p;
    	return ret;
    } 
    
    ll BSGS(ll y, ll z, ll p) {
    	std::map<ll, ll> hash;
    	ll m = ceil(sqrt(p)), t = 1;
    	for (int i = 0; i <= m; i++, z = z * y % p) hash[z] = i;
    	ll s = Qpow(y, m, p);
    	for (int i = 1; i <= m; i++)
    		if (t = t * s % p, hash.count(t)) return i * m - hash[t];
    	return -1;
    }
    
    signed main() {
    	scanf("%d%d", &T, &opt);
    	while (T--) {
    		scanf("%lld%lld%lld", &y, &z, &p);
    		ll ans = 0;
    		if (opt == 1) ans = Qpow(y, z, p) % p;
    		else if (opt == 2) ans = (y % p != 0) ? z * Qpow(y, p - 2, p) % p : -1;
    		else ans = BSGS(y % p, z % p, p);
    		if (ans == -1 || (ans == 0 && opt == 3)) puts("Orz, I cannot find x!");
    		else printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    Problem H: Discrete Logging

    真BSGS板子,秒了

    #include <bits/stdc++.h>
    #define ll long long
    
    ll p, b, n;
    
    ll Qpow(ll x, int b, ll p) {
    	ll ret = 1;
    	for (; b; b >>= 1, x = x * x % p)
    		if (b & 1) ret = ret * x % p;
    	return ret;
    }
    
    ll BSGS(ll a, ll n, ll p) {
    	std::map<ll, ll> hash;
    	ll m = ceil(sqrt(p)), t = 1;
    	for (int i = 0; i <= m; i++, n = n * a % p) hash[n] = i;
    	ll f = Qpow(a, m, p);
    	for (int i = 1; i <= m; i++)
    		if (t = t * f % p, hash.count(t)) return i * m - hash[t];
    	return -1;
    }
    
    signed main() {
    	while (scanf("%lld%lld%lld", &p, &b, &n) != EOF) {
    		ll bsgs = BSGS(b, n, p);
    		if (bsgs == -1) puts("no solution");
    		else printf("%lld
    ", bsgs);
    	}
    	return 0;
    }
    

    Problem I: Matrix

    写个矩阵类,把乘法什么的封装起来。

    仍然懒得写Hash Table,重载小于号塞map,其余照旧

    秒了

    #include <bits/stdc++.h>
    
    int n, p;
    
    struct Matrix {
    	int a[75][75];
    	friend Matrix operator *(Matrix x, Matrix y) {
    		Matrix z = {};
    		for (int k = 1; k <= n; k++)
    			for (int i = 1; i <= n; i++)
    				for (int j = 1; j <= n; j++)
    					z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % p) % p;
    		return z;
    	}
    	void read(int x) {
    		for (int i = 1; i <= x; i++) 
    			for (int j = 1; j <= x; j++)
    				scanf("%d", &a[i][j]);
    	}
        friend bool operator <(Matrix x, Matrix y) {
    		for(int i = 1; i <= n; i++)
    			for(int j = 1; j <= n; j++)
    				if (x.a[i][j] != y.a[i][j]) return x.a[i][j] < y.a[i][j];
    		return 0;
    	}
    } A, B;
    
    void BSGS() {
    	std::map<Matrix, int> hash;
    	int m = ceil(sqrt(p));
    	for (int i = 0; i <= m; i++, B = B * A) hash[B] = i;
    	Matrix f = A;
    	for (int i = 1; i <= m - 1; i++) f = f * A;
    	Matrix t = f;
    	for (int i = 1; i <= m; i++, t = t * f)
    		if (hash.count(t)) printf("%d
    ", i * m - hash[t]), exit(0);
    }
    
    signed main() {
    	scanf("%d%d", &n, &p);
    	A.read(n), B.read(n);
    	BSGS();	
    	return 0;
    }
    
  • 相关阅读:
    sublime text 2安装Emment插件
    PHPExcel IE导出乱码问题
    还是PHPExcel问题
    一条SQL语句查询两表中两个字段
    PHPExcel导出插入图片和居中问题
    jqgrid demo
    openstack horizon 学习(1) 总览
    Python学习笔记
    微软2016校园招聘在线笔试 [Recruitment]
    动态树学习(留坑)
  • 原文地址:https://www.cnblogs.com/gekoo/p/11233875.html
Copyright © 2011-2022 走看看