DRY tak bardzo połamane :(
Tablice mają tylko 2 elementy. Niepotrzebnie kwotę zapisywałeś jako liczbę zmiennoprzecinkową. Mogłeś od razu w groszach jako liczbę zmiennoprzecinkową. Lepiej użyć od razu floor, albo rzutowania na int. Zdecydowanie prościej i czytelniej:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <string>
int main()
{
using namespace std;
const int ile = 3;
int ilosc[ile];
int reszta[ile];
const long double ceny[ile]{ 3.3, 2.4, 2.9 }; //
const std::string nazwy[ile]{ "z grubom okladka", "z miekka okladka", "A4 w linie" };
long double kwota;
cout << " Podaj twoj kapital: ";
cin >> kwota;
cout << "\n";
for (int i = 0; i < ile; i++)
{
cout << "\n Jeden zeszyt " << nazwy[i] << " kosztuje " << int(ceny[i]) << "zl i " << int(ceny[i] * 100) % 100 << " groszy.\n";
ilosc[i] = int(kwota / ceny[i]);
reszta[i] = int(100 * (kwota - (ilosc[i] * ceny[i]))); // reszta w groszach, std::floor przy rzutowaniu
}
cout << "\n\n Wiec za kwote " << kwota << " zlotych mozesz kupic:\n";
for (int i = 0; i < ile; i++)
{
if (kwota < ceny[i])
{
cout << "\n Niestety nie stac cie na ani jeden zeszyt " << nazwy[i];
}
else if (reszta[i] < 100)
{
cout << "\n " << ilosc[i] << " zeszytow " << nazwy[i] << " i zostanie ci " << reszta[i] << " groszy";
}
else if (reszta[i] % 100 == 0)
{
cout << "\n " << ilosc[i] << " zeszytow " << nazwy[i] << " i zostanie ci " << reszta[i] / 100 << " zl";
}
else if (reszta[i] != 0)
{
cout << "\n " << ilosc[i] << " zeszytow " << nazwy[i] << " i zostanie ci "
<< reszta[i] / 100 << " zl i " << reszta[i] % 100 << " groszy";
}
else if (reszta == 0)
{
cout << "\n " << ilosc[i] << " zeszytow " << nazwy[i] << " i nie otrzymujesz reszty";
}
}
}
Posprawdzaj jeszcze wszystko czy działa, bo kod poprawiałem na prędko (bo mi zupa stygnie).