Advertisement
Hezov

Tema (versiunea urata)

Nov 17th, 2024
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.05 KB | None | 0 0
  1. #include <fstream>
  2. using namespace std;
  3. ifstream cin("tema.in");
  4. ofstream cout("tema.out");
  5. const int mxX = 1e6, mxN = 1e5;
  6. long long v[mxN+1], ciur[mxX+1], primes[mxN], p;
  7. long long frecv[mxX+1];
  8. void build_ciur()
  9. {
  10.     ///Precalculam ciurul.
  11.     ciur[0] = ciur[1] = 1;
  12.     for(int i = 4;i<=mxX;i+=2)
  13.         ciur[i] = 1;
  14.     for(int i = 3;i*i<=mxX;i+=2)
  15.         if(ciur[i]==0)
  16.             for(int j = i*i;j<=mxX;j+=2*i)
  17.                 ciur[j] = 1;
  18.     for(int i = 1;i<=mxX;i++)
  19.         if(ciur[i]==0)
  20.             primes[++p] = i;
  21. }
  22. int facMin[mxX+1],facMax[mxX+1];
  23. /// aflam cel mai mic si cel mai mare divizor prim din numere.
  24. void buildFac()
  25. {
  26.     for(int i = 1;i<=p;i++)
  27.         for(int j = primes[i];j<=mxX;j+=primes[i])
  28.         {
  29.             if(facMin[j]==0)
  30.                 facMin[j] = primes[i];
  31.             facMax[j] = primes[i];
  32.         }
  33.  
  34. }
  35. int main()
  36. {
  37.     ///Construim ciurul
  38.     build_ciur();
  39.     ///Citim datele
  40.     long long cerinta, n , k ;
  41.     cin>>cerinta>>n>>k;
  42.     for(int i = 1;i<=n;i++)
  43.             cin>>v[i];
  44.     if(cerinta==1)
  45.     {
  46.         ///Folosim two pointers
  47.         long long sol = 0, compsum = 0, primesum = 0;
  48.         long long stanga = 1;
  49.         for(long long dreapta = 1;dreapta<=n;dreapta++)
  50.         {
  51.             if(v[dreapta]!=1) /// 1 nu afecteaza produsul
  52.             {
  53.                 if(ciur[v[dreapta]]==0) /// daca este prim
  54.                     primesum+=v[dreapta];
  55.                 else compsum+=v[dreapta]; /// daca este compus
  56.             }
  57.             while(compsum*primesum>k) ///garantam ca solutia este valida
  58.             {
  59.                 if(v[stanga]==1) /// nu afecteaza produsul
  60.                     stanga++;
  61.                 else if(ciur[v[stanga]] == 0)
  62.                     primesum-=v[stanga++];
  63.                 else
  64.                     compsum-=v[stanga++];
  65.             }
  66.             sol=max(sol,dreapta-stanga+1);
  67.         }
  68.         cout<<sol<<'\n';
  69.     }
  70.     if(cerinta==2)
  71.     {
  72.         buildFac(); /// aflam cel mai mic si cel mai mare divizor prim din numere.
  73.         int sol = 0, solStanga = -1, solDreapta = -1;
  74.  
  75.         /// Trebuie gasita o proprietate care sa fie buna doar pt o secventa valida
  76.         /// si care sa poata fi verificata in O(1).
  77.  
  78.         /// Un lucru care poate veni in minte este frecventa factorilor primi
  79.         /// prezenti in numerele din secventa. Atunci cel putin unul dintre factori
  80.         /// va avea frecventa egala cu lungimea secventei, daca secventa e valida.
  81.         int stanga = 1;
  82.         for(int dreapta = 1;dreapta<=n;dreapta++)
  83.         {
  84.             if(v[dreapta]==1)
  85.             {
  86.                 //yayyyy
  87.                 while(stanga<dreapta)
  88.                 {
  89.                     if(facMin[v[stanga]]==facMax[v[stanga]])
  90.                         frecv[facMin[v[stanga]]]--,stanga++;
  91.                     else
  92.                     {
  93.                         frecv[facMin[v[stanga]]]--;
  94.                         frecv[facMax[v[stanga]]]--;
  95.                         stanga++;
  96.                     }
  97.                 }
  98.                 stanga = dreapta+1;
  99.                 continue;
  100.             }
  101.             frecv[facMin[v[dreapta]]]++;
  102.             frecv[facMax[v[dreapta]]]++;
  103.             if(facMin[v[dreapta]]==facMax[v[dreapta]]) /// Am adaugat de doua ori la frecventa acelasi factor.
  104.                 frecv[facMin[v[dreapta]]]--;
  105.             while(frecv[facMin[v[dreapta]]]<dreapta-stanga+1&&frecv[facMax[v[dreapta]]]<dreapta-stanga+1)
  106.             {
  107.                 if(facMin[v[stanga]]==facMax[v[stanga]])
  108.                     frecv[facMin[v[stanga]]]--,stanga++;
  109.                 else
  110.                 {
  111.                     frecv[facMin[v[stanga]]]--;
  112.                     frecv[facMax[v[stanga]]]--;
  113.                     stanga++;
  114.                 }
  115.             }
  116.             if(sol <= dreapta-stanga+1)
  117.             {
  118.                 sol = dreapta-stanga+1;
  119.                 solStanga = stanga;
  120.                 solDreapta = dreapta;
  121.             }
  122.  
  123.         }
  124.         cout<<solStanga<<' '<<solDreapta;
  125.  
  126.     }
  127.     return 0;
  128. }
  129.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement