/// Aceasta sursa obtine 100p pe kilonova, cu 67ms timp executie. /// Constrangerile de pe infoarena sunt mai stricte asadar acolo obtine doar 80p (deci exista inca o optimizare). #include #include #include using namespace std; typedef long long ll; ifstream cin("spirala.in"); ofstream cout("spirala.out"); ll v[51][51], desfasurat[51*51], ciclu[51][51], frecv[1200], factori[200]; ll n , k, found, nrdesf, nr_factori; ll sol = 1e18; void desfasoara() { int p = 0; for(int it = 1;it<=n/2;it++) { /// De la stanga la dreapta for(int i = it;i <= n - it + 1;i++) desfasurat[++p] = v[it][i]; /// De sus in jos for(int i = it + 1; i <= n - it + 1; i++) desfasurat[++p] = v[i][n-it+1]; /// De la dreapta la stanga for(int i = n - it; i >= it; i--) desfasurat[++p] = v[n-it+1][i]; /// De jos in sus for(int i = n - it; i > it; i--) desfasurat[++p] = v[i][it]; } if(n % 2 == 1) desfasurat[++p] = v[n/2+1][n/2+1]; } void amesteca() { for(int i = 1;i<=n;i++) for(int j = 1;j<=n;j++) { if(i % 2 == 1) v[i][j] = desfasurat[(i-1)*n + j]; else v[i][j] = desfasurat[i * n - j + 1]; } } void identice() { for(int i = 1;i<=n;i++) for(int j = 1;j<=n;j++) if(ciclu[i][j] == 0) { if(i % 2 == 1 && v[i][j] == (i-1)*n + j) ciclu[i][j] = nrdesf, found++; else if(i % 2 == 0 && v[i][j] == i * n - j + 1) ciclu[i][j] = nrdesf, found++; } } void afisare(int mat[51][51], const int& nr = 0) { if(nr!=0) cout << "MATRICEA #" << nr << ": \n"; for(int i = 1;i<=n;i++, cout << '\n') for(int j = 1;j<=n;j++) cout << setw(3) << mat[i][j] << ' '; } void find_cycles() { while(found != n*n) { nrdesf++; desfasoara(); amesteca(); identice(); //afisare(v,nrdesf); } } void backtracking(const int& index, const ll& current_lcm) { if(current_lcm > 2e9) return; if(index == nr_factori+1) /// au fost toti factorii procesati. { int sum = 0; for(int i = 1;i<=nr_factori;i++) if(current_lcm % factori[i] == 0) sum += frecv[factori[i]]; if(sum == k) sol = min(sol, current_lcm); return; } backtracking(index+1, current_lcm); ll new_lcm = current_lcm * factori[index] / __gcd(current_lcm,factori[index]); backtracking(index+1,new_lcm); return; } int main() { cin >> n >> k; for(int i = 1;i<=n;i++) for(int j = 1;j<=n;j++) { if(i % 2 == 1) v[i][j] = (i-1)*n + j; else v[i][j] = i * n - j + 1; } // afisare(v); find_cycles(); /*cout << "CICLURI" << '\n'; //afisare(ciclu); */ for(int i = 1;i<=n;i++) for(int j = 1;j<=n;j++) frecv[ciclu[i][j]]++; /*for(int i = 1;i<=nrdesf; i++) if(frecv[i]!=0) cout << i << " : " << frecv[i] << '\n';*/ /// Solutia va fi cmmmc dintre o submultime de numere /// {p_1, p_2 ,... p_n} , 1 <= p_i <= nrdesf /// pentru care frecv[p_1] + frecv[p_2] + ... frecv[p_n] = k /// Stim ca cmmmc este numarul obtinut din /// exponentii cei mai mari pentru fiecare numar prim din /// descompunerile in factori primi ale numerelor alese. /// Asadar solutia problemei se va putea scrie sub forma /// sol = d_1 ^ p_1 * d_2 ^ p_2 * ... * d_n ^ p_n. /// Deoarece solutia se garanteaza a fi <= 2e9 inseamna ca /// cmmmc{p_1,p_2,..,p_n} <= 2e9 . /// Observam ca nu putem avea foarte multi factori primi distincti /// In solutie deoarece creste foarte rapid numarul rezultat. /// 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 > 2e9 /// Cu alte cuvinte putem avea maxim 9 factori primi distincti. /// Cu cat avem mai multi factori cu atat puterile factorilor vor /// fi mai mici astfel incat sa se respecte sol <= 2e9 si astfel, /// Un algoritm de backtracking optimizat va putea explora intreg /// search-space-ul fara a depasi limita de timp. /// Un algoritm simplu de backtracking ne arata ca numarul de solutii <= 2e9 este /// cel mult 164k si ca numarul de apelari al functiei este in jur de 1.4 mil. for(int i = 1;i<=nrdesf;i++) if(frecv[i]!=0) factori[++nr_factori] = i; backtracking(1,1); cout << sol << '\n'; return 0; }