您的位置:首页 > 其它

hdu 3221 (指数循环节)

2013-05-16 10:28 344 查看
x^k=x^(k%phi(p)+phi(p))%p( k>=phi(p))

#include <utility>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <bitset>
#include <map>
#include <iterator>
using namespace std;
#define clr(a,v) memset(a,v,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int INF = 0x7f7f7f7f;
const int maxn = 1000002;
const double pi = acos(-1.0);
const double eps = 1e-10;
const int mod = 1000000007;
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<LL> VI;
typedef vector<VI> VVI;
typedef vector<VVI> VVVI;
int a, b, n, p;
LL f[85] = { 1, 0, 1, 1, 2 };
LL g[85] = { 0, 1, 1, 2, 3 };
int phi[maxn + 10];
void init() {
int i, j;
for (i = 2; i <= maxn; ++i)
phi[i] = i;
for (i = 2; i <= maxn; ++i) {
if (phi[i] == i) {
for (j = i; j <= maxn; j += i) {
phi[j] = phi[j] - phi[j] / i;
}
}
}
for (i = 4; i <= 45; ++i) {
f[i] = f[i - 1] + f[i - 2];
g[i] = g[i - 1] + g[i - 2];
}
}
LL POW(LL a, LL b, int mod) {
LL res = 1;
while (b) {
if (b & 1)
res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
VVI A, I, E;
const int size = 2;
VVI multi(const VVI &A, const VVI &B, int mod) {
int i, j, k;
VVI res = VVI(size, VI(size, 0));
for (i = 0; i < size; ++i) {
for (j = 0; j < size; ++j) {
for (k = 0; k < size; ++k) {
res[i][j] += A[i][k] * B[k][j];
res[i][j] %= mod;
}
}
}
return res;
}
VVI cal(const VVI& A, LL k, int mod) {
VVI res = E, t = A;
while (k) {
if (k & 1)
res = multi(res, t, mod);
t = multi(t, t, mod);
k >>= 1;
}
return res;
}
LL go(int n, LL a, LL b, int p) {
if (p == 1)
return 0;
LL ans = 0;
if (n <= 40) {
ans = POW(a, f
, p);
ans = ans * POW(b, g
, p) % p;
return ans;
}
int mod = phi[p];
VVI res = cal(A, n - 1, mod);
LL t1 = res[0][1], t2 = res[0][0];
t1 += mod, t2 += mod;
t1 = POW(a, t1, p);
t2 = POW(b, t2, p);
ans = t1 * t2 % p;
return ans;
}
int main() {
ios::sync_with_stdio(false);
E = I = A = VVI(2, VI(2, 0));
E[0][0] = E[1][1] = 1;
I[0][0] = I[0][1] = I[1][0] = 1;
A = I;
init();
int T, cas;
scanf("%d", &T);
for (cas = 1; cas <= T; ++cas) {
scanf("%d%d%d%d", &a, &b, &p, &n);
printf("Case #%d: %I64d\n", cas, go(n - 1, a, b, p));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: