1. 程式人生 > >hdu 3221 (指數迴圈節)

hdu 3221 (指數迴圈節)

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[n], p);
		ans = ans * POW(b, g[n], 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;
}