给定整数N ,任务是找到路数N!可以分为两个不同的因子A和B ,使得A和B是互素的。由于答案可能非常大,因此请以10 9 + 7为模数打印。
例子:
Input: N = 5
Output: 4
Explanation: The pairs are (1, 120), (3, 40), (5, 24), (8, 15).
Input: N = 7
Output: 8
Explanation: The pairs are (1, 5040), (5, 1008), (7, 720), (9, 560), (16, 315), (35, 144), (45, 112), (63, 80).
天真的方法:最简单的方法是计算N的阶乘!并生成其所有因子,并检查是否有任何一对因子(i,j)的GCD (i,j)== 1 。
时间复杂度: O(√N!)
辅助空间: O(1)
高效方法:为了优化上述方法,其思想是找到N的不同素数因子,然后计算将其分为两个不同的互素因子A和B的方法。请按照以下步骤解决问题:
- 每个正整数都可以表示为素数幂的乘积(素数分解)。因此, N的每个可能值都可以表示为N = 2 p ×3 q ×5 r …..(p≥0,q≥0,r≥0) 。
- 现在,任务是将N分为两个不同的互质因子。可以通过每次将N的素数分解中的每个项分配为两个可能的组合来完成。
插图:
Let N = 18900.
Expressing N in the form of its prime factors, 18900 = 22 * 33 * 52 * 71
Each of 22, 33, 52 and 71 can be assigned to either of the two factors. Using product rule in combinatorics, the total possible ways are 24 = 16. Since the two factors have no order, the total possible ways are 23 = 8. Therefore, the number of ways N is 2X – 1, where X is the number of prime-factors of N.
请按照以下步骤解决问题:
- N的素数分解!包含所有小于或等于N的素数。
- 如果x是质数小于或等于N的数,则方式数N! (阶乘)可以分为两个不同的互素因数,它们等于2 x – 1 。
- 预先计算的素数的数目∀N≤N使用埃拉托塞尼的筛,并将它们存储在数组中。
- 要对10 9 + 7取模,请使用模幂,即x x y %p 。
下面是上述方法的实现:
C++
// C++ Program for the above approach
#include
using namespace std;
// Maximum value of N
#define MAXN 1000000
// Stores at each indices if
// given number is prime or not
int is_prime[MAXN] = { 0 };
// Stores count_of_primes
int count_of_primes[MAXN] = { 0 };
// Function to generate primes
// using Sieve of Eratsothenes
void sieve()
{
for (int i = 3; i < MAXN; i += 2) {
// Assume all odds are primes
is_prime[i] = 1;
}
for (int i = 3; i * i < MAXN; i += 2) {
// If a prime is encountered
if (is_prime[i])
for (int j = i * i; j < MAXN;
j += i) {
// Mark all its multiples
// as non-prime
is_prime[j] = 0;
}
}
is_prime[2] = 1;
// Count primes <= MAXN
for (int i = 1; i < MAXN; i++)
count_of_primes[i]
= count_of_primes[i - 1]
+ is_prime[i];
}
// Function to calculate (x ^ y) % p
// in O(log y)
long long int power(long long int x,
long long int y,
long long int p)
{
long long result = 1;
while (y > 0) {
if (y & 1 == 1)
result = (result * x) % p;
x = (x * x) % p;
y >>= 1;
}
return result;
}
// Utility function to count the number of ways
// N! can be split into co-prime factors
void numberOfWays(int N)
{
long long int count
= count_of_primes[N] - 1;
long long int mod = 1000000007;
long long int answer
= power(2, count, mod);
if (N == 1)
answer = 0;
cout << answer;
}
// Driver Code
int main()
{
// Calling sieve function
sieve();
// Given N
int N = 7;
// Function call
numberOfWays(N);
return 0;
}
Java
// Java Program for the above approach
import java.util.*;
class GFG {
// Maximum value of N
static final int MAXN = 1000000;
// Stores at each indices if
// given number is prime or not
static int is_prime[];
// Stores count_of_primes
static int count_of_primes[];
// Function to generate primes
// using Sieve of Eratsothenes
static void sieve()
{
is_prime = new int[MAXN];
count_of_primes = new int[MAXN];
Arrays.fill(is_prime, 0);
Arrays.fill(count_of_primes, 0);
for (int i = 3; i < MAXN; i += 2) {
// Assume all odds are primes
is_prime[i] = 1;
}
for (int i = 3; i * i < MAXN; i += 2) {
// If a prime is encountered
if (is_prime[i] == 1) {
for (int j = i * i; j < MAXN;
j += i) {
// MArk all its multiples
// as non-prime
is_prime[j] = 0;
}
}
}
is_prime[2] = 1;
// Count all primes upto MAXN
for (int i = 1; i < MAXN; i++)
count_of_primes[i]
= count_of_primes[i - 1] + is_prime[i];
}
// Function to calculate (x ^ y) % p
// in O(log y)
static long power(long x, long y, long p)
{
long result = 1;
while (y > 0) {
if ((y & 1) == 1)
result = (result * x) % p;
x = (x * x) % p;
y >>= 1;
}
return result;
}
// Utility function to count the number of
// ways N! can be split into two co-prime factors
static void numberOfWays(int N)
{
long count = count_of_primes[N] - 1;
long mod = 1000000007;
long answer = power(2, count, mod);
if (N == 1)
answer = 0;
long ans = answer;
System.out.println(ans);
}
// Driver Code
public static void main(String[] args)
{
// Calling sieve function
sieve();
// Given N
int N = 7;
// Function call
numberOfWays(N);
}
}
Python3
# Python3 program for the above approach
import math
# Maximum value of N
MAXN = 1000000
# Stores at each indices if
# given number is prime or not
is_prime = [0] * MAXN
# Stores count_of_primes
count_of_primes = [0] * MAXN
# Function to generate primes
# using Sieve of Eratsothenes
def sieve():
for i in range(3, MAXN, 2):
# Assume all odds are primes
is_prime[i] = 1
for i in range(3, int(math.sqrt(MAXN)), 2):
# If a prime is encountered
if is_prime[i]:
for j in range(i * i, MAXN, i):
# Mark all its multiples
# as non-prime
is_prime[j] = 0
is_prime[2] = 1
# Count primes <= MAXN
for i in range(1, MAXN):
count_of_primes[i] = (count_of_primes[i - 1] +
is_prime[i])
# Function to calculate (x ^ y) % p
# in O(log y)
def power(x, y, p):
result = 1
while (y > 0):
if y & 1 == 1:
result = (result * x) % p
x = (x * x) % p
y >>= 1
return result
# Utility function to count the number of ways
# N! can be split into co-prime factors
def numberOfWays(N):
count = count_of_primes[N] - 1
mod = 1000000007
answer = power(2, count, mod)
if N == 1:
answer = 0
print(answer)
# Driver Code
if __name__ == "__main__":
# Calling sieve function
sieve()
# Given N
N = 7
# Function call
numberOfWays(N)
# This code is contributed by akhilsaini
C#
// C# program for the above approach
using System;
class GFG{
// Maximum value of N
static int MAXN = 1000000;
// Stores at each indices if
// given number is prime or not
static int[] is_prime;
// Stores count_of_primes
static int[] count_of_primes;
// Function to generate primes
// using Sieve of Eratsothenes
static void sieve()
{
is_prime = new int[MAXN];
count_of_primes = new int[MAXN];
Array.Fill(is_prime, 0);
Array.Fill(count_of_primes, 0);
for(int i = 3; i < MAXN; i += 2)
{
// Assume all odds are primes
is_prime[i] = 1;
}
for(int i = 3; i * i < MAXN; i += 2)
{
// If a prime is encountered
if (is_prime[i] == 1)
{
for(int j = i * i; j < MAXN; j += i)
{
// MArk all its multiples
// as non-prime
is_prime[j] = 0;
}
}
}
is_prime[2] = 1;
// Count all primes upto MAXN
for(int i = 1; i < MAXN; i++)
count_of_primes[i] = count_of_primes[i - 1] +
is_prime[i];
}
// Function to calculate (x ^ y) % p
// in O(log y)
static long power(long x, long y, long p)
{
long result = 1;
while (y > 0)
{
if ((y & 1) == 1)
result = (result * x) % p;
x = (x * x) % p;
y >>= 1;
}
return result;
}
// Utility function to count the number of
// ways N! can be split into two co-prime factors
static void numberOfWays(int N)
{
long count = count_of_primes[N] - 1;
long mod = 1000000007;
long answer = power(2, count, mod);
if (N == 1)
answer = 0;
long ans = answer;
Console.Write(ans);
}
// Driver Code
public static void Main()
{
// Calling sieve function
sieve();
// Given N
int N = 7;
// Function call
numberOfWays(N);
}
}
// This code is contributed by akhilsaini
8
时间复杂度: O(log(log(N))+ log(N))
辅助空间: O(N)