Advertisement
Hezov

Spirala OJI X 2003

Jan 30th, 2025
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.64 KB | None | 0 0
  1. /// Aceasta sursa obtine 100p pe kilonova, cu 67ms timp executie.
  2. /// Constrangerile de pe infoarena sunt mai stricte asadar acolo obtine doar 80p (deci exista inca o optimizare).
  3. #include <fstream>
  4. #include <algorithm>
  5. #include <iomanip>
  6. using namespace std;
  7. typedef long long ll;
  8. ifstream cin("spirala.in");
  9. ofstream cout("spirala.out");
  10. ll v[51][51], desfasurat[51*51], ciclu[51][51], frecv[1200], factori[200];
  11. ll n , k, found, nrdesf, nr_factori;
  12. ll sol = 1e18;
  13. void desfasoara()
  14. {
  15.     int p = 0;
  16.     for(int it = 1;it<=n/2;it++)
  17.     {
  18.         /// De la stanga la dreapta
  19.         for(int i = it;i <= n - it + 1;i++)
  20.             desfasurat[++p] = v[it][i];
  21.         /// De sus in jos
  22.         for(int i = it + 1; i <= n - it + 1; i++)
  23.             desfasurat[++p] = v[i][n-it+1];
  24.         /// De la dreapta la stanga
  25.         for(int i = n - it; i >= it; i--)
  26.             desfasurat[++p] = v[n-it+1][i];
  27.         /// De jos in sus
  28.         for(int i = n - it; i > it; i--)
  29.             desfasurat[++p] = v[i][it];
  30.     }
  31.     if(n % 2 == 1) desfasurat[++p] = v[n/2+1][n/2+1];
  32. }
  33.  
  34. void amesteca()
  35. {
  36.     for(int i = 1;i<=n;i++)
  37.         for(int j = 1;j<=n;j++)
  38.         {
  39.             if(i % 2 == 1)
  40.                 v[i][j] = desfasurat[(i-1)*n + j];
  41.             else v[i][j] = desfasurat[i * n - j + 1];
  42.         }
  43. }
  44. void identice()
  45. {
  46.     for(int i = 1;i<=n;i++)
  47.         for(int j = 1;j<=n;j++)
  48.             if(ciclu[i][j] == 0)
  49.             {
  50.                 if(i % 2 == 1 && v[i][j] == (i-1)*n + j)
  51.                     ciclu[i][j] = nrdesf, found++;
  52.                 else if(i % 2 == 0 && v[i][j] == i * n - j + 1)
  53.                     ciclu[i][j] = nrdesf, found++;
  54.             }
  55. }
  56. void afisare(int mat[51][51], const int& nr = 0)
  57. {
  58.     if(nr!=0)
  59.         cout << "MATRICEA #" << nr << ": \n";
  60.     for(int i = 1;i<=n;i++, cout << '\n')
  61.         for(int j = 1;j<=n;j++)
  62.             cout << setw(3) << mat[i][j] << ' ';
  63. }
  64. void find_cycles()
  65. {
  66.     while(found != n*n)
  67.     {
  68.         nrdesf++;
  69.         desfasoara();
  70.         amesteca();
  71.         identice();
  72.         //afisare(v,nrdesf);
  73.     }
  74. }
  75.  
  76. void backtracking(const int& index, const ll& current_lcm)
  77. {
  78.     if(current_lcm > 2e9)
  79.         return;
  80.     if(index == nr_factori+1) /// au fost toti factorii procesati.
  81.     {
  82.         int sum = 0;
  83.         for(int i = 1;i<=nr_factori;i++)
  84.             if(current_lcm % factori[i] == 0)
  85.                 sum += frecv[factori[i]];
  86.         if(sum == k)
  87.             sol = min(sol, current_lcm);
  88.         return;
  89.     }
  90.     backtracking(index+1, current_lcm);
  91.     ll new_lcm = current_lcm * factori[index] / __gcd(current_lcm,factori[index]);
  92.     backtracking(index+1,new_lcm);
  93.     return;
  94. }
  95. int main()
  96. {
  97.     cin >> n >> k;
  98.     for(int i = 1;i<=n;i++)
  99.         for(int j = 1;j<=n;j++)
  100.         {
  101.             if(i % 2 == 1)
  102.                 v[i][j] = (i-1)*n + j;
  103.             else v[i][j] = i * n - j + 1;
  104.         }
  105.     // afisare(v);
  106.     find_cycles();
  107.     /*cout << "CICLURI" << '\n';
  108.     //afisare(ciclu); */
  109.  
  110.     for(int i = 1;i<=n;i++)
  111.         for(int j = 1;j<=n;j++)
  112.             frecv[ciclu[i][j]]++;
  113.  
  114.     /*for(int i = 1;i<=nrdesf; i++)
  115.         if(frecv[i]!=0)
  116.             cout << i << " : " << frecv[i] << '\n';*/
  117.  
  118.     /// Solutia va fi cmmmc dintre o submultime de numere
  119.     /// {p_1, p_2 ,... p_n} , 1 <= p_i <= nrdesf
  120.     /// pentru care frecv[p_1] + frecv[p_2] + ... frecv[p_n] = k
  121.  
  122.     /// Stim ca cmmmc este numarul obtinut din
  123.     /// exponentii cei mai mari pentru fiecare numar prim din
  124.     /// descompunerile in factori primi ale numerelor alese.
  125.  
  126.     /// Asadar solutia problemei se va putea scrie sub forma
  127.     /// sol = d_1 ^ p_1 * d_2 ^ p_2 * ... * d_n ^ p_n.
  128.  
  129.     /// Deoarece solutia se garanteaza a fi <= 2e9 inseamna ca
  130.     /// cmmmc{p_1,p_2,..,p_n} <= 2e9 .
  131.  
  132.     /// Observam ca nu putem avea foarte multi factori primi distincti
  133.     /// In solutie deoarece creste foarte rapid numarul rezultat.
  134.     /// 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 > 2e9
  135.     /// Cu alte cuvinte putem avea maxim 9 factori primi distincti.
  136.  
  137.     /// Cu cat avem mai multi factori cu atat puterile factorilor vor
  138.     /// fi mai mici astfel incat sa se respecte sol <= 2e9 si astfel,
  139.     /// Un algoritm de backtracking optimizat va putea explora intreg
  140.     /// search-space-ul fara a depasi limita de timp.
  141.  
  142.     /// Un algoritm simplu de backtracking ne arata ca numarul de solutii <= 2e9 este
  143.     /// cel mult 164k si ca numarul de apelari al functiei este in jur de 1.4 mil.
  144.  
  145.     for(int i = 1;i<=nrdesf;i++)
  146.         if(frecv[i]!=0)
  147.             factori[++nr_factori] = i;
  148.     backtracking(1,1);
  149.     cout << sol << '\n';
  150.     return 0;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement