Cod sursa(job #3302093)

Utilizator mgntMarius B mgnt Data 3 iulie 2025 00:09:57
Problema Sandokan Scor 100
Compilator c-64 Status done
Runda Arhiva de probleme Marime 2.32 kb

#include <stdio.h>

#include <inttypes.h>


#define PRIME_P  UINT64_C(2000003)


uint64_t modular_inverse (uint64_t a) {
    
    uint64_t  e = 0;
    
    uint64_t  b = 0;
    
    uint64_t  p = 0;
    
    uint64_t  x = 0;
    
    e = PRIME_P - 2;
    
    b = 1; // b: 2ᵏ, for k := 0, 1, …, ⌊log₂(e)⌋
    
    p = a; // p: aᵇ
    
    x = 1;
    
    while (0 != e) {
       
       if (0 != (b & e)) {
           
           x *= p;
           
           x %= PRIME_P;
           
           e ^= b;
       }
       
       b += b;
       
       p *= p;
       
       p %= PRIME_P;
       
    }
    
    return x;
    
}


int main (void) {
    
    FILE  * f = NULL;
    
    FILE  * g = NULL;
    
    uint64_t  k = 0;
    
    uint64_t  n = 0;
    
    uint64_t  m = 0;
    
    uint64_t  j = 0;
    
    uint64_t  q = 0;
    
    uint64_t  a = 0;
    
    uint64_t  b = 0;
    
    uint64_t  c = 0;
    
    uint64_t  w = 0;
    
    
    f = fopen("sandokan.in", "r");
    
    g = fopen("sandokan.out", "w");
    
    (void) fscanf(f, "%" SCNu64 "%" SCNu64, &n, &k);
    
    
    /* (ⁿ⁻¹ ₘ₋₁) = (n − 1)!·((n − m)!)⁻¹·((m − 1)!)⁻¹ 
     * 
     *  a:  (n − m)!,   b:  (m − 1)!,  c:  (n − 1)!
     *         
     *  w:  c·b⁻¹·a⁻¹ (mod PRIME_P);   w is the answer.
     *  
     *  m = k − 1, when n is a multiple of k − 1, and n % (k − 1), otherwise,
     *  because each possibility is a subset of containing any m − 1 elements of
     *  the initial set without its max element, and the initial max element.
     *  
     */
    
    if (0 != (n % (k - 1))) {
        
        m = n % (k - 1);
    }
    else {
        
        m = k - 1;
    }
    
    
    j = 0;
    
    q = 1;  // q: j!
    
    while (j < n) {
        
        if (j == (n - m)) { a = q; }
        
        if (j == (m - 1)) { b = q; }
        
        if (j == (n - 1)) { c = q; }
        
        j += 1;
        
        q *= j;
        
        q %= PRIME_P;
    }
    
    
    w  = c;                    w %= PRIME_P;
                                    
    w *= modular_inverse(b);   w %= PRIME_P;
                                    
    w *= modular_inverse(a);   w %= PRIME_P;
    
    
    (void) fprintf(g, "%" PRIu64 "\n", w);
    
    
    (void) fclose(g);
    
    (void) fclose(f);
    
    return 0;
}