bhupixb

What the hell

Oct 17th, 2019
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.72 KB | None | 0 0
  1. // Simon St James (ssjgz) - 2019-09-09
  2. //
  3. // Solution to: https://www.codechef.com/SEPT19B/problems/GDSUB
  4. //
  5. #define SUBMISSION
  6. #define BRUTE_FORCE
  7. #ifdef SUBMISSION
  8. #undef BRUTE_FORCE
  9. #define NDEBUG
  10. #endif
  11. #include <iostream>
  12. #include <vector>
  13. #include <algorithm>
  14.  
  15. #include <cassert>
  16.  
  17. #include <sys/time.h> // TODO - this is only for random testcase generation.  Remove it when you don't need new random testcases!
  18.  
  19. using namespace std;
  20.  
  21. const int64_t Mod = 1'000'000'007ULL;
  22.  
  23. class ModNum
  24. {
  25.    public:
  26.        ModNum(int64_t n = 0)
  27.            : m_n{n}
  28.        {
  29.            assert(n >= 0);
  30.        }
  31.        ModNum& operator+=(const ModNum& other)
  32.        {
  33.            m_n = (m_n + other.m_n) % Mod;
  34.            return *this;
  35.        }
  36.        ModNum& operator-=(const ModNum& other)
  37.        {
  38.            m_n = (Mod + m_n - other.m_n) % Mod;
  39.            return *this;
  40.        }
  41.        ModNum& operator*=(const ModNum& other)
  42.        {
  43.            m_n = (m_n * other.m_n) % Mod;
  44.            return *this;
  45.        }
  46.        int64_t value() const { return m_n; };
  47.    private:
  48.        int64_t m_n;
  49. };
  50.  
  51. ModNum operator+(const ModNum& lhs, const ModNum& rhs)
  52. {
  53.    ModNum result(lhs);
  54.    result += rhs;
  55.    return result;
  56. }
  57.  
  58. ModNum operator-(const ModNum& lhs, const ModNum& rhs)
  59. {
  60.    ModNum result(lhs);
  61.    result -= rhs;
  62.    return result;
  63. }
  64.  
  65. ModNum operator*(const ModNum& lhs, const ModNum& rhs)
  66. {
  67.    ModNum result(lhs);
  68.    result *= rhs;
  69.    return result;
  70. }
  71.  
  72. bool operator==(const ModNum& lhs, const ModNum& rhs)
  73. {
  74.    return lhs.value() == rhs.value();
  75. }
  76.  
  77. ostream& operator<<(ostream& os, const ModNum& toPrint)
  78. {
  79.    os << toPrint.value();
  80.    return os;
  81. }
  82.  
  83. template <typename T>
  84. T read()
  85. {
  86.    T toRead;
  87.    cin >> toRead;
  88.    assert(cin);
  89.    return toRead;
  90. }
  91.  
  92. vector<int> getPrimesUpTo8000()
  93. {
  94.  
  95.    const int largestPrime = 8000;
  96.    vector<bool> isPrime(largestPrime + 1, true);
  97.    vector<int> primesUpTo8000;
  98.    for (int64_t factor = 2; factor <= largestPrime; factor++)
  99.    {
  100.        const bool isFactorPrime = isPrime[factor];
  101.        assert(factor < isPrime.size());
  102.        if (isFactorPrime)
  103.        {
  104.            primesUpTo8000.push_back(factor);
  105.        }
  106.        for (int64_t multiple = factor * factor; multiple < isPrime.size(); multiple += factor)
  107.        {
  108.            if (!isPrime[multiple] && !isFactorPrime)
  109.            {
  110.                // This multiple has already been marked, and since factor is not prime,
  111.                // all subsequent multiples will already have been marked (by any of the
  112.                // prime factors of factor!), so we can stop here.
  113.                break;
  114.            }
  115.            isPrime[multiple] = false;
  116.        }
  117.    }
  118.    return primesUpTo8000;
  119. }
  120.  
  121. ModNum solveBruteForce(int N, int K, const vector<int>& a)
  122. {
  123.    ModNum result;
  124.  
  125.    vector<bool> useElement(N, false);
  126.  
  127.    while (true)
  128.    {
  129.        vector<int> subset;
  130.        for (int i = 0; i < N; i++)
  131.        {
  132.            if (useElement[i])
  133.                subset.push_back(a[i]);
  134.        }
  135.        sort(subset.begin(), subset.end());
  136.        const auto isGood = subset.size() <= K && (unique(subset.begin(), subset.end()) == subset.end());
  137.        if (isGood)
  138.        {
  139.            result = result + 1;
  140.        }
  141.  
  142.        int index = 0;
  143.        while (index < N && useElement[index])
  144.        {
  145.            useElement[index] = false;
  146.            index++;
  147.        }
  148.        if (index == N)
  149.            break;
  150.  
  151.        useElement[index] = true;
  152.    }
  153.    
  154.    return result;
  155. }
  156.  
  157. ModNum solveOptimised(const int N, const int K, const vector<int>& aOriginal)
  158. {
  159.    auto a = aOriginal;
  160.    sort(a.begin(), a.end());
  161.    struct PrimeInfo
  162.    {
  163.        int prime = -1;
  164.        int numOccurrences = 0;
  165.    };
  166.    vector<PrimeInfo> distinctPrimeOccurrences;
  167.  
  168.    int prevPrime = -1;
  169.    while (!a.empty())
  170.    {
  171.        const int prime = a.back();
  172.        if (prime != prevPrime)
  173.        {
  174.            distinctPrimeOccurrences.push_back({prime, 0});
  175.        }
  176.        distinctPrimeOccurrences.back().numOccurrences++;
  177.  
  178.        a.pop_back();
  179.        prevPrime = prime;
  180.    }
  181.    const int numDistinctElements = distinctPrimeOccurrences.size();
  182.  
  183. #if 0
  184.    for (const auto x : distinctPrimeOccurrences)
  185.    {
  186.        cout << " prime: " << x.prime << " occurs " << x.numOccurrences << " times" << endl;
  187.    }
  188. #endif
  189.  
  190.    vector<vector<ModNum>> dp(numDistinctElements + 1, vector<ModNum>(numDistinctElements + 1, 0));
  191.    for (int i = 0; i <= numDistinctElements; i++)
  192.    {
  193.        dp[i][0] = 1;
  194.    }
  195.  
  196.    //vector<int> numForEachChoices(K + 1);
  197.    //solveBruteForce(N, K, aOriginal, numForEachChoices);
  198.    int64_t blah = 0;
  199.    for (int i = 1; i <= numDistinctElements; i++)
  200.    {
  201.        for (int j = 1; j <= i; j++)
  202.        {
  203.            blah++;
  204.            assert(i - 1 >= 0);
  205.            dp[i][j] += dp[i - 1][j]; // Don't choose this number.
  206.             //cout << " i: " << i << " j: " << j << " dp[i - 1][j]: " << dp[i - 1][j] << endl;
  207.             assert(j - 1 >= 0 && j - 1 <= i - 1);
  208.  
  209.             // Do choose *one* from this bunch of same numbers.
  210.             //cout << " i: " << i << " j: " << j << " dp[i - 1][j - 1]: " << dp[i - 1][j - 1] << endl;
  211.             dp[i][j] += dp[i - 1][j - 1] * (distinctPrimeOccurrences[i - 1].numOccurrences);
  212.  
  213.             //cout << "i: " << i << " j: " << j << " dp: " << dp[i][j] << endl;
  214.         }
  215.     }
  216.     //cout << "numDistinctElements: " << numDistinctElements << endl;
  217.     //cout << "blah: " << blah << endl;
  218.  
  219.     ModNum result;
  220.  
  221.     for (int j = 0; j <= min(K, numDistinctElements); j++)
  222.     {
  223.         //cout << "j: " << j << " numForEachChoices: " << numForEachChoices[j] << " dp:" << dp[numDistinctElements][j] << endl;
  224.         //assert(numForEachChoices[j] == dp[numDistinctElements][j]);
  225.         result += dp[numDistinctElements][j];
  226.     }
  227.    
  228.    
  229.     return result;
  230. }
  231.  
  232. int main(int argc, char* argv[])
  233. {
  234.     ios::sync_with_stdio(false);
  235.     if (argc == 2 && string(argv[1]) == "--test")
  236.     {
  237.         struct timeval time;
  238.         gettimeofday(&time,NULL);
  239.         srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
  240.  
  241. #if 0
  242.         cout << "primesUpTo8000: " << primesUpTo8000.size() << endl;
  243.         for (int i = 0;i < primesUpTo8000.size(); i++)
  244.         {
  245.             cout << " i: " << i << " primesUpTo8000: " << primesUpTo8000[i] << endl;
  246.         }
  247. #endif
  248.  
  249.         const auto primesUpTo8000 = getPrimesUpTo8000();
  250.         int N = 100'000;
  251.        const int K = primesUpTo8000.size();
  252.        //const int maxPrimeIndex = (rand() % (primesUpTo8000.size() - 1) + 1);
  253.        //const int maxPrimeIndex = 9;
  254.  
  255.  
  256.        cout << N << " " << K << endl;
  257.  
  258.        for (int i = 0; i < primesUpTo8000.size(); i++)
  259.        {
  260.            cout << primesUpTo8000[i] << " ";
  261.            N--;
  262.        }
  263.        while (N > 0)
  264.        {
  265.            cout << primesUpTo8000[rand() % primesUpTo8000.size()] << " ";
  266.            N--;
  267.        }
  268.        cout << endl;
  269.  
  270.  
  271.  
  272.        return 0;
  273.    }
  274.  
  275.  
  276.    const int N = read<int>();
  277.    const int K = read<int>();
  278.  
  279.    vector<int> a(N);
  280.    for (auto& aElement : a)
  281.    {
  282.        aElement = read<int>();
  283.    }
  284.  
  285. #ifdef BRUTE_FORCE
  286. #if 1
  287.    const auto solutionBruteForce = solveBruteForce(N, K, a);
  288.    cout << "solutionBruteForce: " << solutionBruteForce << endl;
  289. #endif
  290. #if 1
  291.    const auto solutionOptimised = solveOptimised(N, K, a);
  292.    cout << "solutionOptimised:  " << solutionOptimised << endl;
  293.  
  294.    assert(solutionOptimised == solutionBruteForce);
  295. #endif
  296. #else
  297.    const auto solutionOptimised = solveOptimised(N, K, a);
  298.    cout << solutionOptimised << endl;
  299. #endif
  300.  
  301.    assert(cin);
  302. }
Add Comment
Please, Sign In to add comment