📜  将阶乘n表示为连续数字的总和

📅  最后修改于: 2021-05-05 00:44:29             🧑  作者: Mango

给定两个数字N和M。找出可以将阶乘N表示为两个或多个连续数字之和的方式的数目。打印结果以M为模。

例子:

Input : N = 3, M = 7
Output : 1
Explanation:  3! can be expressed 
in one way, i.e. 1 + 2 + 3 = 6. 
Hence 1 % 7 = 1

Input : N = 4, M = 7
Output : 1
Explanation:  4! can be expressed 
in one way, i.e. 7 + 8 + 9 = 24
Hence 1 % 7 = 1

一个简单的解决方案是先计算阶乘,然后使用计数方法将一个数表示为连续数之和,将表示阶乘的方法数计数为连续数之和。此解决方案导致溢出。

以下是避免溢出的更好解决方案
让我们考虑r个连续数字的总和表示为:
(a + 1)+(a + 2)+(a + 3)+…+(a + r),简化为(r *(r + 2 * a + 1))/ 2
因此,(a +1)+(a + 2)+(a + 3)+…+(a + r)=(r *(r + 2 * a +1))/ 2。对于阶乘N,我们将其写为
2 * N! = r *(r + 2 * a +1)
而不是计算所有对(r,a),我们将计算所有对(r,r + 2 * a +1)。现在,我们只计算XY = 2 * N的所有有序对(X,Y)!其中X 为了计算N!中的除数的数量,我们计算了因式分解的质数的幂,除数的总数变为(p 1 +1)*(p 2 +1)*…*(p n +1)。要计算N!中素数的最大幂,我们将使用Legendre公式。
\nu _{p}(n!)=\sum _{{i=1}}^{{\infty }}\left\lfloor {\frac {n}{p^{i}}}\right\rfloor,
下面是上述方法的实现。

C++
// CPP program to count number of
// ways we can express a factorial
// as sum of consecutive numbers
#include 
using namespace std;
  
#define MAX 50002
  
vector primes;
  
// sieve of Eratosthenes to compute
// the prime numbers
void sieve()
{
    bool isPrime[MAX];
    memset(isPrime, true, sizeof(isPrime));
  
    for (int p = 2; p * p < MAX; p++) {
        if (isPrime[p] == true) {
            for (int i = p * 2; i < MAX; i += p)
                isPrime[i] = false;
        }
    }
  
    // Store all prime numbers
    for (int p = 2; p < MAX; p++)
        if (isPrime[p])
            primes.push_back(p);
}
  
// function to calculate the largest
// power of a prime in a number
long long int power(long long int x,
                    long long int y)
{
    long long int count = 0;
    long long int z = y;
    while (x >= z) {
        count += (x / z);
        z *= y;
    }
    return count;
}
  
// Modular multiplication to avoid
// the overflow of multiplication
// Please see below for details
// https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/
long long int modMult(long long int a,
                      long long int b,
                      long long int mod)
{
    long long int res = 0;
    a = a % mod;
    while (b > 0) {
        if (b % 2 == 1)
            res = (res + a) % mod;
        a = (a * 2) % mod;
        b /= 2;
    }
    return res % mod;
}
  
// Returns count of ways to express n!
// as sum of consecutives.
long long int countWays(long long int n,
                        long long int m)
{
    long long int ans = 1;
  
    // We skip 2 (First prime) as we need to
    // consider only odd primes
    for (int i = 1; i < primes.size(); i++) {
  
        // compute the largest power of prime
        long long int powers = power(n, primes[i]);
  
        // if the power of current prime number
        // is zero in N!, power of primes greater
        // than current prime number will also
        // be zero, so break out from the loop
        if (powers == 0)
            break;
  
        // multiply the result at every step
        ans = modMult(ans, powers + 1, m) % m;
    }
  
    // subtract 1 to exclude the case of 1
    // being an odd divisor
    if (((ans - 1) % m) < 0)
        return (ans - 1 + m) % m;
    else
        return (ans - 1) % m;
}
  
// Driver Code
int main()
{
    sieve();
    long long int n = 4, m = 7;
    cout << countWays(n, m);
    return 0;
}


Java
// Java program to count number of
// ways we can express a factorial
// as sum of consecutive numbers
import java.util.*;
  
class GFG {
      
    static int MAX = 50002;
    static ArrayList primes 
                 = new ArrayList();
                   
    // sieve of Eratosthenes to compute
    // the prime numbers
    public static void sieve()
    {
          
        boolean isPrime[] = new boolean[MAX];
          
        for(int i = 0; i < MAX; i++)
            isPrime[i] = true;
              
        for (int p = 2; p * p < MAX; p++) {
            if (isPrime[p] == true) {
                for (int i = p * 2; i < MAX; i += p)
                    isPrime[i] = false;
            }
        }
          
        // Store all prime numbers
        for (int p = 2; p < MAX; p++)
            if (isPrime[p] == true)
                primes.add(p);
    }
          
    // function to calculate the largest
    // power of a prime in a number
    public static int power(int x, int y)
    {
        int count = 0;
        int z = y;
        while (x >= z) {
            count += (x / z);
            z *= y;
        }
          
        return count;
    }
      
    // Modular multiplication to avoid
    // the overflow of multiplication
    // Please see below for details
    // https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/
    public static int modMult(int a, int b, int mod)
    {
        int res = 0;
        a = a % mod;
        while (b > 0) {
            if (b % 2 == 1)
                res = (res + a) % mod;
            a = (a * 2) % mod;
            b /= 2;
        }
          
        return res % mod;
    }
      
    // Returns count of ways to express n!
    // as sum of consecutives.
    public static int countWays(int n, int m)
    { 
        int ans = 1;
      
        // We skip 2 (First prime) as we need to
        // consider only odd primes
        for (int i = 1; i < primes.size(); i++) {
      
            // compute the largest power of prime
            int powers = power(n, primes.get(i));
      
            // if the power of current prime number
            // is zero in N!, power of primes greater
            // than current prime number will also
            // be zero, so break out from the loop
            if (powers == 0)
                break;
      
            // multiply the result at every step
            ans = modMult(ans, powers + 1, m) % m;
        }
      
        // subtract 1 to exclude the case of 1
        // being an odd divisor
        if (((ans - 1) % m) < 0)
            return (ans - 1 + m) % m;
        else
            return (ans - 1) % m;
    }
      
    //Driver function
    public static void main (String[] args) {
          
        sieve();
          
        int n = 4, m = 7; 
          
        System.out.println(countWays(n,m));
    }
}
  
// This code is contributed by akash1295.


Python 3
# Python 3 program to count number of
# ways we can express a factorial
# as sum of consecutive numbers
MAX = 50002;
  
primes = []
  
# sieve of Eratosthenes to compute
# the prime numbers
def sieve():
    isPrime = [True]*(MAX)
      
    p = 2
    while p * p < MAX :
        if (isPrime[p] == True):
            for i in range( p * 2,MAX, p):
                isPrime[i] = False
        p+=1
  
    # Store all prime numbers
    for p in range( 2,MAX):
        if (isPrime[p]):
            primes.append(p)
  
# function to calculate the largest
# power of a prime in a number
def power( x, y):
  
    count = 0
    z = y
    while (x >= z):
        count += (x // z)
        z *= y
      
    return count
  
# Modular multiplication to avoid
# the overflow of multiplication
# Please see below for details
# https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/
def modMult(a, b,mod):
    res = 0
    a = a % mod
    while (b > 0):
        if (b % 2 == 1):
            res = (res + a) % mod
        a = (a * 2) % mod
        b //= 2
      
    return res % mod
  
# Returns count of ways to express n!
# as sum of consecutives.
def countWays(n,m):
    ans = 1
  
    # We skip 2 (First prime) as we need to
    # consider only odd primes
    for i in range(1,len(primes)):
  
        # compute the largest power of prime
        powers = power(n, primes[i])
  
        # if the power of current prime number
        # is zero in N!, power of primes greater
        # than current prime number will also
        # be zero, so break out from the loop
        if (powers == 0):
            break
  
        # multiply the result at every step
        ans = modMult(ans, powers + 1, m) % m
      
  
    # subtract 1 to exclude the case of 1
    # being an odd divisor
    if (((ans - 1) % m) < 0):
        return (ans - 1 + m) % m
    else:
        return (ans - 1) % m
  
# Driver Code
if __name__ == "__main__":
    sieve()
    n = 4
    m = 7
    print(countWays(n, m))
      
# This code is contributed by ChitraNayal


C#
// C# program to count number of 
// ways we can express a factorial 
// as sum of consecutive numbers 
using System ;
using System.Collections;
  
class GFG { 
      
    static int MAX = 50002; 
    static ArrayList primes = new ArrayList (); 
                  
    // sieve of Eratosthenes to compute 
    // the prime numbers 
    public static void sieve() 
    { 
          
        bool []isPrime = new bool[MAX]; 
          
        for(int i = 0; i < MAX; i++) 
            isPrime[i] = true; 
              
        for (int p = 2; p * p < MAX; p++) { 
            if (isPrime[p] == true) { 
                for (int i = p * 2; i < MAX; i += p) 
                    isPrime[i] = false; 
            } 
        } 
          
        // Store all prime numbers 
        for (int p = 2; p < MAX; p++) 
            if (isPrime[p] == true) 
                primes.Add(p); 
    } 
          
    // function to calculate the largest 
    // power of a prime in a number 
    public static int power_prime(int x, int y) 
    { 
        int count = 0; 
        int z = y; 
        while (x >= z) { 
            count += (x / z); 
            z *= y; 
        } 
          
        return count; 
    } 
      
    // Modular multiplication to avoid 
    // the overflow of multiplication 
    // Please see below for details 
    // https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/ 
    public static int modMult(int a, int b, int mod) 
    { 
        int res = 0; 
        a = a % mod; 
        while (b > 0) { 
            if (b % 2 == 1) 
                res = (res + a) % mod; 
            a = (a * 2) % mod; 
            b /= 2; 
        } 
          
        return res % mod; 
    } 
      
    // Returns count of ways to express n! 
    // as sum of consecutives. 
    public static int countWays(int n, int m) 
    { 
        int ans = 1; 
      
        // We skip 2 (First prime) as we need to 
        // consider only odd primes 
        for (int i = 1; i < primes.Count; i++) { 
      
            // compute the largest power of prime 
            int powers = power_prime(n, Convert.ToInt32(primes[i])); 
      
            // if the power of current prime number 
            // is zero in N!, power of primes greater 
            // than current prime number will also 
            // be zero, so break out from the loop 
            if (powers == 0) 
                break; 
      
            // multiply the result at every step 
            ans = modMult(ans, powers + 1, m) % m; 
        } 
      
        // subtract 1 to exclude the case of 1 
        // being an odd divisor 
        if (((ans - 1) % m) < 0) 
            return (ans - 1 + m) % m; 
        else
            return (ans - 1) % m; 
    } 
      
    //Driver function 
    public static void Main () { 
          
        sieve(); 
          
        int n = 4, m = 7; 
          
        Console.WriteLine(countWays(n,m)); 
    } 
} 
  
// This code is contributed by Ryuga


输出:
1