#include <array>
#include <iostream>
#include <map>
#define ll int_fast64_t
struct posredni_wynik
{
ll wspolczynniki_od;
ll suma;
};
ll pierwsze_wzmocnienie(ll od, ll po, ll wzmocnienie)
{
if (!(od<= po))
{
return -1;
}
ll bitow_w_od = __builtin_popcountll(od);
if (bitow_w_od == wzmocnienie)
{
return od;
}
else if (bitow_w_od < wzmocnienie)
{
ll bit = 1;
ll wynik = od;
while (__builtin_popcountll(wynik) < wzmocnienie)
{
if (!(bit & wynik))
{
wynik += bit;
}
bit <<= 1;
}
if (wynik <= po)
{
return wynik;
}
return -1;
}
else
{
ll bit = 1;
ll wynik = od;
while (__builtin_popcountll(wynik) > wzmocnienie)
{
if (bit & wynik)
{
wynik -= bit;
}
bit <<= 1;
}
while (!(wynik & bit))
{
bit <<= 1;
}
wynik += bit;
if (wynik <= po)
{
return wynik;
}
return -1;
}
}
ll najmniejsze_wzmocnienie(ll od, ll po)
{
if (od == 0)
{
return 0;
}
for (ll i = 1; i <= 61; ++i)
{
ll wynik = pierwsze_wzmocnienie(od, po, i);
if (wynik != -1)
{
return i;
}
}
return 0;
}
ll najwieksze_wzmocnienie(ll od, ll po)
{
if (po == 0)
{
return 0;
}
for (ll i = 61; i > 0; --i)
{
ll wynik = pierwsze_wzmocnienie(od, po, i);
if (wynik != -1)
{
return i;
}
}
return 0;
}
int main()
{
ll bitow;
ll najw_wspolczynnik;
std::map<ll, posredni_wynik> posrednie_wyniki;
std::map<ll, posredni_wynik> nastepne_wyniki;
std::array<ll, 205> bity;
std::cin >> bitow >> najw_wspolczynnik;
// std::cerr << bitow << ' ' << najw_wspolczynnik << ' ' << std::endl;
for (int i = 0; i < bitow; ++i)
{
std::cin >> bity[i];
// std::cerr << bity[i] << std::endl;
}
posrednie_wyniki[0] = {0, 0};
for (int bit = 0; bit < bitow; ++bit)
{
// std::cerr << 'a' << std::endl;
nastepne_wyniki.clear();
for (auto it = posrednie_wyniki.begin(); it != posrednie_wyniki.end(); ++it)
{
ll wz_od = najmniejsze_wzmocnienie(it->second.wspolczynniki_od, najw_wspolczynnik);
ll wz_do = najwieksze_wzmocnienie(it->second.wspolczynniki_od, najw_wspolczynnik);
// std::cerr << it->second.wspolczynniki_od << ',' << najw_wspolczynnik << '^' << wz_od << ' ' << wz_do << std::endl;
for (ll wzmocnienie = wz_od; wzmocnienie <= wz_do; ++wzmocnienie)
{
ll wspolczynnik = pierwsze_wzmocnienie(it->second.wspolczynniki_od, najw_wspolczynnik, wzmocnienie);
// std::cerr << it->second.wspolczynniki_od << ',' << najw_wspolczynnik << '^' << wzmocnienie << ' ' << wspolczynnik << std::endl;
if (wspolczynnik == -1)
{
continue;
}
ll suma = it->second.suma + wzmocnienie * bity[bit];
auto istniejacy_wynik = nastepne_wyniki.find(wspolczynnik);
if (istniejacy_wynik == nastepne_wyniki.end() || istniejacy_wynik->second.suma < suma)
{
nastepne_wyniki[wspolczynnik] = {wspolczynnik + 1, suma};
}
}
}
// std::cerr << 'd' << std::endl;
posrednie_wyniki.clear();
ll najwieksza_suma = 0;
for (auto it = nastepne_wyniki.begin(); it != nastepne_wyniki.end(); ++it)
{
if (it == nastepne_wyniki.begin() || it->second.suma > najwieksza_suma)
{
posrednie_wyniki[it->first] = it->second;
najwieksza_suma = it->second.suma;
}
}
}
std::cout << posrednie_wyniki.rbegin()->second.suma << std::endl;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #include <array> #include <iostream> #include <map> #define ll int_fast64_t struct posredni_wynik { ll wspolczynniki_od; ll suma; }; ll pierwsze_wzmocnienie(ll od, ll po, ll wzmocnienie) { if (!(od<= po)) { return -1; } ll bitow_w_od = __builtin_popcountll(od); if (bitow_w_od == wzmocnienie) { return od; } else if (bitow_w_od < wzmocnienie) { ll bit = 1; ll wynik = od; while (__builtin_popcountll(wynik) < wzmocnienie) { if (!(bit & wynik)) { wynik += bit; } bit <<= 1; } if (wynik <= po) { return wynik; } return -1; } else { ll bit = 1; ll wynik = od; while (__builtin_popcountll(wynik) > wzmocnienie) { if (bit & wynik) { wynik -= bit; } bit <<= 1; } while (!(wynik & bit)) { bit <<= 1; } wynik += bit; if (wynik <= po) { return wynik; } return -1; } } ll najmniejsze_wzmocnienie(ll od, ll po) { if (od == 0) { return 0; } for (ll i = 1; i <= 61; ++i) { ll wynik = pierwsze_wzmocnienie(od, po, i); if (wynik != -1) { return i; } } return 0; } ll najwieksze_wzmocnienie(ll od, ll po) { if (po == 0) { return 0; } for (ll i = 61; i > 0; --i) { ll wynik = pierwsze_wzmocnienie(od, po, i); if (wynik != -1) { return i; } } return 0; } int main() { ll bitow; ll najw_wspolczynnik; std::map<ll, posredni_wynik> posrednie_wyniki; std::map<ll, posredni_wynik> nastepne_wyniki; std::array<ll, 205> bity; std::cin >> bitow >> najw_wspolczynnik; // std::cerr << bitow << ' ' << najw_wspolczynnik << ' ' << std::endl; for (int i = 0; i < bitow; ++i) { std::cin >> bity[i]; // std::cerr << bity[i] << std::endl; } posrednie_wyniki[0] = {0, 0}; for (int bit = 0; bit < bitow; ++bit) { // std::cerr << 'a' << std::endl; nastepne_wyniki.clear(); for (auto it = posrednie_wyniki.begin(); it != posrednie_wyniki.end(); ++it) { ll wz_od = najmniejsze_wzmocnienie(it->second.wspolczynniki_od, najw_wspolczynnik); ll wz_do = najwieksze_wzmocnienie(it->second.wspolczynniki_od, najw_wspolczynnik); // std::cerr << it->second.wspolczynniki_od << ',' << najw_wspolczynnik << '^' << wz_od << ' ' << wz_do << std::endl; for (ll wzmocnienie = wz_od; wzmocnienie <= wz_do; ++wzmocnienie) { ll wspolczynnik = pierwsze_wzmocnienie(it->second.wspolczynniki_od, najw_wspolczynnik, wzmocnienie); // std::cerr << it->second.wspolczynniki_od << ',' << najw_wspolczynnik << '^' << wzmocnienie << ' ' << wspolczynnik << std::endl; if (wspolczynnik == -1) { continue; } ll suma = it->second.suma + wzmocnienie * bity[bit]; auto istniejacy_wynik = nastepne_wyniki.find(wspolczynnik); if (istniejacy_wynik == nastepne_wyniki.end() || istniejacy_wynik->second.suma < suma) { nastepne_wyniki[wspolczynnik] = {wspolczynnik + 1, suma}; } } } // std::cerr << 'd' << std::endl; posrednie_wyniki.clear(); ll najwieksza_suma = 0; for (auto it = nastepne_wyniki.begin(); it != nastepne_wyniki.end(); ++it) { if (it == nastepne_wyniki.begin() || it->second.suma > najwieksza_suma) { posrednie_wyniki[it->first] = it->second; najwieksza_suma = it->second.suma; } } } std::cout << posrednie_wyniki.rbegin()->second.suma << std::endl; } |
English