先看简单点的。求 (5+2*√(6))^n % 1024
第一种构造:
原文:https://blog.csdn.net/xtulollipop/article/details/52382791
第二种:
令
An = (5 + 2√6)^n,Bn = (5 - 2√6)^n
Sn = An + Bn;
显然Sn是正整数,且Bn是小于1的
所以答案就是Sn - 1!
(5 + 2√6) + (5 - 2√6) = 10;
Sn* [(5 + 2√6) + (5 - 2√6)]
= ((5 + 2√6)n + (5 - 2√6)n) * [(5 + 2√6) + (5 - 2√6)]
= (5 + 2√6)^(n+1) + (5 - 2√6)^(n+1) + (5 + 2√6)^(n-1) + (5 - 2√6)^(n-1)
∴10 * Sn = Sn+1 + Sn-1
Sn+1 = 10 * Sn - Sn-1
Sn = 10*Sn-1 - Sn-2;
到这里我们就可以通过构造矩阵来解决了!
| Sn | |10 -1| | Sn-1|
| Sn-1| = |1 0 | * | Sn-2|
然后再看一个更难的:

记An=(a+sqrt(b))^n,Bn=(a-sqrt(b))^n Cn=An+Bn,很容易知道。。 Cn是整数,
然后由于a b的范围可以知道Bn在0-1开区间之间,因此Sn=[Cn]%mod,接下来对Cn进行配项。。。
Cn+1=(a+sqrt(b))^n*(a+sqrt(b))+(a-sqrt(b))^n*(a-sqrt(b)),貌似没啥用,但是要充分利用共轭这个式子。
要想办法让(a+sqrt(b))*(a-sqrt(b))=a*a-b派上用场,然后继续去把它拿去配项。。。
一开始我拿Cn*(a*a-b)未果,于是用Cn-1*(a*a-b)结合上述的Cn+1就得到了:
Cn+1=(a+sqrt(b))^n*(a+sqrt(b))+(a-sqrt(b))^n*(a-sqrt(b))
Cn-1*(a*a-b)=(a+sqrt(b))^n*(a-sqrt(b))+(a-sqrt(b))^n*(a+sqrt(b))
加减消去根号项得到:Cn+1=2*a*Cn+(b-a*a)*Cn-1,公式化简完毕,2*2阶矩阵可以直接写了:
|2*a b-a*a| | Cn | | Cn+1|
|1 0 |* | Cn-1|= | Cn |
---------------------
作者:田益铭
原文:https://blog.csdn.net/u012860063/article/details/48862383
然后看这神仙题
,求[y]%M。
根据上面的分析知道是,显然
。
这里x巨大无比,题解说是循环群,找到循环节(循环节和模数M有关)以后把指数部分模一下循环节再矩阵快速幂。
Orz。
至于为什么是矩阵循环群?不如问问神奇的海螺?
不过既然被知道是循环群了,那么生成元是我还是知道的,找的是这个群的循环节,也就是找满足取模情况下
的n。
求到的循环节可以存储下来,暴力求,至于为什么暴力求,你为什么不问问神奇的海螺?,应该是t是10^3,M是10^4,不卡常也就过了。。
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
const int N = (1<<8)+5;
const int M = 50000;
typedef long long ll;
#define se second
#define fi first
#define rep(i, n, m) for(int i = (n); i <= (m); i++)
struct Mat {
ll m[2][2];
Mat() {
rep(i, 0, 1) rep(j, 0, 1) m[i][j] = 0;
}
}I;
Mat Mul(Mat a, Mat b, int mod)
{
Mat ans;
rep(i, 0, 1) rep(j, 0, 1) rep(k, 0, 1) {
ans.m[i][j] += a.m[i][k] * b.m[k][j];
ans.m[i][j] %= mod;
}
return ans;
}
Mat MatPower(Mat a, ll b, ll mod)
{
Mat ans = I;
while(b) {
if(b & 1) ans = Mul(ans, a, mod);
a = Mul(a, a, mod);
b >>= 1;
}
return ans;
}
ll power(ll a, ll b, ll mod)
{
ll ans = 1;
while(b) {
if(b & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ans;
}
int cir[M], Mod[M], t, x, m;
Mat a, b, ans;
void findmod(ll mod)
{
if(Mod[mod]) return;
cir[0] = 2;
cir[1] = 10;
for(int i= 2; ; i++) {
cir[i] = (cir[i - 1] * 10 - cir[i - 2] + mod) % mod;
if(cir[i] == cir[1] && cir[i - 1] == cir[0]) {
Mod[mod] = i - 1;
break;
}
}
//cir[0] =
}
int main () {
#ifndef ONLINE_JUDGE
freopen("data.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
I.m[0][0] = I.m[1][1] = 1;
cin >> t;
a.m[0][1] = -1;
a.m[1][0] = 1;
a.m[1][1] = 0;
int Case = 1;
while(t--) {
cin >> x >> m;
findmod(m);
a.m[0][0] = 10 % m;
b.m[0][0] = 10 % m;
b.m[1][0] = 2 % m;
ans = MatPower(a, ((1+power(2, x, Mod[m]))%Mod[m] - 1 + Mod[m])%Mod[m], m);
ans = Mul(ans, b, m);
printf("Case #%d: %d\n", Case++, (ans.m[0][0] + m - 1) % m);
}
return 0;
}
本文深入探讨了数学算法中求解特定形式的指数表达式模运算问题,通过构造矩阵和利用循环群理论,提供了一种高效解决大规模指数运算的方法。文章详细介绍了如何通过矩阵快速幂和寻找循环节来简化复杂计算,并提供了具体的编程实现。

313

被折叠的 条评论
为什么被折叠?



