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;

}

你可能感兴趣的:(simple)