Fzu 2020 composite number returns the remainder of the prime number

Source: Internet
Author: User

1) based on the following formula, directly calculate

C (n, m) mod p = N * ''' * (N-m + 1)/(1 * ''' * m) mod p

Calculate the number of P in the NN, denominator mm, and the remainder of P. If the number of P in the numerator is greater than the number of P in the denominator, the result is 0,

If not, the original formula is NN/mm mod P (NN, P) = 1, (mm, P) = 1

At this time, how to find the reverse element becomes crucial. There are two solutions below.

2) Lucas theorem: used to evaluate the value of C (n, m) mod P, and P is a prime number.

Description:

Lucas (n, m, p) = C (n % P, M % P) * Lucas (N/P, M/P, P)

Lucas (n, 0, P) = 1;

While

C (a, B) = A * (A-1) * ''' * (a-B + 1)/(1*2 * ''' * B) % P,

The numerator is aa denominator and BB, So C (a, B) = AA/BB % P (the same as above)

At this point, the reverse yuan method is also very important. The reverse yuan method will be explained as follows.

Supplementary knowledge: reverse Element Method

(A/B) mod p = A * (B inverse) mod p

B * x = 1 (mod p) x is the reverse element of B.

The inverse B can be obtained using the Extended Euclidean or Euler's function:

1). Extended Euclidean: B * x + p * y = 1 has a solution, and X is what we want

2 ). euler's function: B ^ (p-1) = 1 (mod P), so B * B ^ (P-2) = 1 (mod P), So X = B ^ (P-2)

To sum up, method 1 can be regarded as brute force computing, while method 2 only converts a large number into a number, and then uses method 1 for calculation, which reduces the time.

Method 1: Calculate directly. The Code is as follows:

#include<stdio.h>
#define LL long long
int pnum, x, y;
int getMultMod(int start, int end, int p) {
int i, j;
LL res;
for (i = start, res = 1, pnum = 0; i <= end; i++) {
if (i % p == 0) {
j = i;
while (j % p == 0) {
pnum++;
j /= p;
}
res = res * j % p;
} else {
res = res * i % p;
}
}
return (int) (res % p);
}
void extend_gcd(int a, int b) {
int xx;
if (b == 0) {
x = 1, y = 0;
return;
}
extend_gcd(b, a % b);
xx = x;
x = y, y = xx - a / b * y;
}
void solve(int n, int m, int p) {
int a, b, apnum, bpnum;
LL res;
a = getMultMod(n - m + 1, n, p);
apnum = pnum;
b = getMultMod(1, m, p);
bpnum = pnum;
if (apnum > bpnum) {
puts("0");
return;
} else {
extend_gcd(b, p);
res = (LL) x;
res = (res % p + p) % p;
res = res * a % p;
printf("%I64d\n", res);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int t, n, m, p;
scanf("%d", &t);
while (t--) {
scanf("%d %d %d", &n, &m, &p);
solve(n, m, p);
}
return 0;
}

You can rewrite several methods based on different reverse elements as follows:

int modular_exp(int a, int b, int p) {
LL res, temp;
res = 1 % p, temp = a % p;
while (b) {
if (b & 1) {
res = res * temp % p;
}
temp = temp * temp % p;
b >>= 1;
}
return (int) res;
}
void solve(int n, int m, int p) {
int a, b, apnum, bpnum;
LL res;
a = getMultMod(n - m + 1, n, p);
apnum = pnum;
b = getMultMod(1, m, p);
bpnum = pnum;
if (apnum > bpnum) {
puts("0");
return;
} else {
res = modular_exp(b, p - 2, p);
res = res * a % p;
printf("%I64d\n", res);
}
}

Method 2: using the Lucas theorem, the Code is as follows:

#include<stdio.h>
#define LL long long
int x, y;
void extend_gcd(int a, int b) {
int xx;
if (b == 0) {
x = 1, y = 0;
return;
}
extend_gcd(b, a % b);
xx = x;
x = y, y = xx - a / b * y;
}
int C(int a, int b, int p) {
int i;
LL resa, resb, res;
if (b > a) {
return 0;
}
for (i = 0, resa = 1, resb = 1; i < b; i++) {
resa = resa * (a - i) % p, resb = resb * (b - i) % p;
}
extend_gcd(resb, p);
res = (LL) x;
res = (res % p + p) % p;
res = res * resa % p;
return (int) res;
}
void solve(int n, int m, int p) {
int a, b;
LL res;
res = 1;
while (n || m) {
a = n % p, b = m % p;
res = res * C(a, b, p) % p;
n /= p, m /= p;
}
printf("%I64d\n", res);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int t, n, m, p;
scanf("%d", &t);
while (t--) {
scanf("%d %d %d", &n, &m, &p);
solve(n, m, p);
}
return 0;
}

Based on different reverse elements, the preceding methods can be rewritten as follows:

int modular_exp(int a, int b, int p) {
LL res, temp;
res = 1 % p, temp = a % p;
while (b) {
if (b & 1) {
res = res * temp % p;
}
temp = temp * temp % p;
b >>= 1;
}
return (int) res;
}
int C(int a, int b, int p) {
int i;
LL resa, resb, res;
if (b > a) {
return 0;
}
for (i = 0, resa = 1, resb = 1; i < b; i++) {
resa = resa * (a - i) % p, resb = resb * (b - i) % p;
}
res = modular_exp(resb, p - 2, p);
res = res * resa % p;
return (int) res;
}

Summary: The methods involved in this type of problem include the inverse element method (Extended Euclidean algorithm, knowledge of Euler's functions (involving the return of large numbers), the Lucas theorem, and the Group Union number.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.