uva 10692 - Huge Mods 指数循环节

这题也是求多重指数解取模,和hdu 的2837 有点像

公式 

A^x % m = A^(x%phi(m)+phi(m)) % m (x >= phi(m))
这里的A和m不一定互质,这样问题就很简单了,附上代码。

#include <stdio.h>
#define LL long long

const int maxn = 1000;
bool vis[maxn];
int pri[maxn], num, a[22];

void get_prime() {
	int i, j;
	vis[1] = 1;
	for(i = 2;i*i <= maxn; i++) if(!vis[i])
		for(j = i*i;j <= maxn;j += i)	vis[j] = 1;
	num = 0;
	for(i = 2;i <= maxn; i++) if(!vis[i])
		pri[num++] = i;
}

int euler(int n) {
	int ans = n;
	for(int i = 0;i < num && pri[i]*pri[i] <= n; i++) {
		if(n%pri[i] == 0) {
			ans = ans-ans/pri[i];
			while(n%pri[i] == 0)
				n /= pri[i];
		}
	}
	if(n > 1)	ans = ans - ans/n;
	return ans;
}

LL powmod(LL x, LL n, LL mod) {
	LL ret = 1;
	LL now = 1;
	for(int i = 0;i < n; i++) {
		now *= x;
		if(now >= mod)	break;
	}
	if(now >= mod)	now = mod;
	else	now = 0;
	while(n) {
		if(n&1) ret = ret*x%mod;
		x = x*x%mod;
		n /= 2;
	}
	return ret + now;
}

LL Jay(LL now, LL m, LL n) {
	if(now == n) {
		if(a[now] >= m)	return a[now]%m + m;
		return a[now];
	}
	LL cur = euler(m);
	LL up = Jay(now+1, cur, n);
	LL ans = powmod(a[now], up, m);
	return ans ;
}

char s[111];
int main() {
	get_prime();
	LL n, m;
	int i;
	int cas = 1;
	while(scanf("%s", s) != -1 && s[0] != '#') {
		printf("Case #%d: ", cas++);
		sscanf(s, "%lld", &m);
		scanf("%lld", &n);
		for(i = 1;i <= n ;i++)	scanf("%lld", &a[i]);
		LL ans = Jay(1, m, n);
		printf("%lld\n", ans%m);
	}
	return 0;
}


你可能感兴趣的:(uva 10692 - Huge Mods 指数循环节)