Eu sei que esse tópico não é discutido, mas eu fiz dessa maneira. Eu também tinha problema envolvendo os centavos. Essa maneira é bem simples, eu resolvi transformar o valor em reais para centavos, no caso multiplicando por 100, assim não teria problema com arredondamentos no meio dos cálculos.
Existe maneiras melhores de fazer, mas essa é fácil de compreender.
#include<stdio.h>
#include<stdlib.h>
#include<locale.h>
int main()
{
setlocale(LC_ALL, "Portuguese"); //Configurando para o suporte da Língua Portuguesa.
float DinheiroI,DinheiroF;
int N100,N50,N20,N10,N5,N2;
int M1,M_50,M_25,M_10,M_05,M_01;
printf("Informe um valor em reais: R$");
scanf("%f",&DinheiroI);
DinheiroF=DinheiroI*100;
N100=DinheiroF/10000;
DinheiroF=DinheiroF-N100*10000;
N50=DinheiroF/5000;
DinheiroF=DinheiroF-N50*5000;
N20= DinheiroF/2000;
DinheiroF=DinheiroF-N20*2000;
N10=DinheiroF/1000;
DinheiroF=DinheiroF-N10*1000;
N5=DinheiroF/500;
DinheiroF=DinheiroF-N5*500;
N2=DinheiroF/200;
DinheiroF=DinheiroF-N2*200;
M1=DinheiroF/100;
DinheiroF=DinheiroF-M1*100;
M_50=DinheiroF/50;
DinheiroF=DinheiroF-M_50*50;
M_25=DinheiroF/25;
DinheiroF=DinheiroF-M_25*25;
M_10=DinheiroF/10;
DinheiroF=DinheiroF-M_10*10;
M_05=DinheiroF/5;
DinheiroF=DinheiroF-M_05*5;
M_01=DinheiroF;
printf("\nO valor informado: R$%.2f.",DinheiroI);
printf("\n\nO número de notas de R$100 é: %d", (N100));
printf("\nO número de notas de R$50 é: %d", (N50));
printf("\nO número de notas de R$20 é: %d", (N20));
printf("\nO número de notas de R$10 é: %d", (N10));
printf("\nO número de notas de R$5 é: %d", (N5));
printf("\nO número de notas de R$2 é: %d", (N2));
printf("\nO número de moedas de R$1 é: %d", (M1));
printf("\nO número de moedas de R$0,50 é: %d", (M_50));
printf("\nO número de moedas de R$0,25 é: %d", (M_25));
printf("\nO número de moedas de R$0,10 é: %d", (M_10));
printf("\nO número de moedas de R$0,05 é: %d", (M_05));
printf("\nO número de moedas de R$0,01 é: %d\n\n", (M_01));
system("pause");
return 0;
}