toj 2991 Simple Task II 二次剩余

/*
 * toj2991.c
 *
 *  Created on: 2011-10-13
 *      Author: bjfuwangzhu
 */
/*
 给出整数n,统计二次同余方程x^2=1(mod n)在[0,n)闭区间上的解的个数。
 分析:
 根据《简明数论》上的说明:
 若p是素数,x^2=1(mod p^k)的解数有如下结论。
 当p==2时,k==1则解数是1,k==2时解数是2,k>=3时,解数是4。
 当p>2时,k>0时解数是2。
 然后分解因数。
 */
#include<math.h>
#include<stdio.h>
#include<string.h>
#define nmax 46345
int flag[nmax], prime[nmax], plen;
int pfactor[nmax], cpfactor[nmax], len_factor;
void mkprime() {
	int i, j;
	memset(flag, -1, sizeof(flag));
	for (i = 2, plen = 0; i < nmax; i++) {
		if (flag[i]) {
			prime[plen++] = i;
		}
		for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) {
			flag[i * prime[j]] = 0;
			if (i % prime[j] == 0) {
				break;
			}
		}
	}
}
void findpFactor(int n) {
	int i, te, cnt;
	te = (int) sqrt(n * 1.0);
	for (i = 0, len_factor = 0; (i < plen) && (prime[i] <= te); i++) {
		if (n % prime[i] == 0) {
			cnt = 0;
			while (n % prime[i] == 0) {
				cnt++;
				n /= prime[i];
			}
			pfactor[len_factor] = prime[i];
			cpfactor[len_factor++] = cnt;
		}
	}
	if (n > 1) {
		pfactor[len_factor] = n;
		cpfactor[len_factor++] = 1;
	}
}
void solve(int n) {
	int i, res;
	if (n == 1) {
		puts("0");
		return;
	}
	findpFactor(n);
	for (i = 0, res = 1; i < len_factor; i++) {
		if (pfactor[i] == 2) {
			if (cpfactor[i] >= 3) {
				res = res * 4;
			} else {
				res = res * cpfactor[i];
			}
		} else {
			res = res * 2;
		}
	}
	printf("%d\n", res);
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("data.in", "r", stdin);
#endif
	int n;
	mkprime();
	while (~scanf("%d", &n), n) {
		solve(n);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/xiaoxian1369/p/2210335.html