Cod sursa(job #2703814)

Utilizator mgntMarius B mgnt Data 9 februarie 2021 12:19:31
Problema Mins Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 7.59 kb
#include <fstream>                                                                  
#include <cstdint>                                                                  
#include <cstddef>                                                                  
#include <vector>                                                                   
#include <algorithm>                                                                
#include <stdexcept>                                                                
                                                                                    
typedef  std::size_t    size_t;                                                     
typedef  std::uint8_t   uint8_t;                                                    
typedef  std::uint32_t  uint32_t;                                                   
typedef  std::uint64_t  uint64_t;                                                   
                                                                                    
                                                                                    
int main (void);                                                                    
    void demo (void);                                                               
        uint64_t solve (size_t  c, size_t  d);                                      
            void scan_distinct_prime_factors (size_t  q);                           
            uint32_t  count__non_coprimes (void);                                   
                                                                                    
                                                                                    
int main (void) {                                                                   
                                                                                    
    int  status = 17;                                                               
                                                                                    
    try {                                                                           
        demo();                                                                     
        status = 0; }                                                               
    catch ( ... ) {                                                                 
        status = 5; }                                                               
                                                                                    
    return status;                                                                  
}                                                                                   
                                                                                    
                                                                                    
void demo (void) {                                                                  
                                                                                    
    std::ifstream  is("mins.in");                                                   
    size_t  c = 0;                                                                  
    size_t  d = 0;                                                                  
    is >> c >> d;                                                                   
                                                                                    
    if (1 <= c && c <= 1000000 && 1 <= d && d <= 1000000) {} else {                 
        throw std::invalid_argument("At least one of c and d is a bad apple.");  }  
                                                                                    
    uint64_t  const answer = solve(c, d);                                           
                                                                                    
    std::ofstream  os("mins.out");                                                  
    os << answer << '\n';                                                           
                                                                                    
}                                                                                   
                                                                                    
                                                                                    
uint64_t solve(size_t  c, size_t  d) {                                              
                                                                                    
    /// Determines the number of y/x fractions,                                     
    /// 1 ≤ x ≤ c − 1, 1 ≤ y ≤ d − 1, gcd(y, x) = 1,                                
    /// given integers  c  and  d,  1 ≤ c ≤ 1.000.000,  1 ≤ d ≤ 1.000.000.          
                                                                                    
    if ((1 == c) || (1 == d)) {                                                     
        return 0;  }                                                                
                                                                                    
    if (c > d) {                                                                    
        std::swap(c, d);  }                                                         
                                                                                    
    std::vector<uint8_t>  size(c, 0);                                               
    std::vector<uint32_t>  signature(c, 1);                                         
    for (size_t  p = 2; c > p; ++p) {                                               
        if (size[p] == 0) {                                                         
            for (size_t  q = p; c > q; q += p) {                                    
                size[q] += 1;                                                       
                signature[q] *= static_cast<uint32_t>(p);  }}}                      
                                                                                    
    // There are d − 1 irreducible fractios 1/y, y ← 1 … d − 1.                     
    uint64_t  const d0 = d - 1;                                                     
    uint64_t  const c0 = c - 1;                                                     
    uint64_t  total = d0;                                                           
    // The principle of inclusion-exclusion at work, bulk counting and summing,     
    // the sizes of the sets A[x][d] = {y ∈ ℤ | 1 ≤ y ≤ d − 1, gcd(x, y) ≠ 1}.      
    total += (c - 2) * (d - 1);                                                     
    for (size_t  q = 2; c > q; ++q) {                                               
        uint8_t   s = size[signature[q]];                                           
        if (0 != s) {                                                               
            uint64_t  const k = d0 / q;                                             
            uint64_t  const f = c0 / q;                                             
            total = ((s & 1) == 0) ? (total + f * k) : (total - f * k);             
            size[q] = 0;  }}                                                        
                                                                                    
    return total;                                                                   
                                                                                    
}