Cod sursa(job #980275)
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
using namespace std;
ifstream f("cifre.in");
ofstream g("cifre.out");
#define Cifmax 10
int cifra[Cifmax];
int dp[Cifmax][Cifmax];
int A, B, C, K;
void citeste(){
f >> A >> B >> C >> K;
}
void desc(int X){
int x2 = X; int cnt = 0;
for(; x2!=0; x2/=10){
++cnt;
}
for(int i=cnt; X!=0; --i){
cifra[i] = X % 10; X /= 10;
}
cifra[0] = cnt;
//for(int i=0; i<=cifra[0]; ++i) cout << cifra[i] << " "; cout << "\n";
}
void faDinamica(int tip){
for(int i=0; i<Cifmax; ++i){
for(int j=0; j<Cifmax; ++j) dp[i][j] = 0;
}
if (tip > 0){// iau in considerare
if (C != 0){
dp[1][1] = 1;
dp[1][0] = 8; // mai raman opt numere care nu contin cifra C ( pe 0 nu il pot pune)
}else {// e chiara 0 cifra cautata => nu il pot puine => dp[1][0] = 9;
dp[1][0] = 9;
}
}else {// pot pune 0 de la inceput
dp[1][1] = 1;
dp[1][0] = 9; // mai raman 9 numare ( ca l-am scos pe ala care il contine pe C);
}
for(int i=2; i<cifra[0]; ++i){
for(int j=0; j<i; ++j){// o cifra poate aparea maxim de i-1 ori pt ca lungimea acum e abia i
dp[i][j] += (dp[i-1][j] * 9); // adica la numerele cu j cifre de tipul C pun cifre care nu sunt la fel cu C
dp[i][j+1] += dp[i-1][j];
}
}
}
void baga(int poz, int cnt, int &Rez){
// cnt = de cate ori apare cifra C in numarul X de la inceput pana la a poz-a cifra(fara poz)
if (poz == cifra[0]){
if (cnt >= K) Rez += cifra[poz] + 1;// adica acum le pot pune pe toate
else if (cnt + 1 == K && C <= cifra[poz]) Rez += 1;// cnda pun chiar C
return;
}
if (C == 0 && poz == 1) baga(poz+1, cnt, Rez);// nu am ce face nu am voie sa il pun pe 0
int deUnde = 0;
if (poz == 1) deUnde = 1;
for(int i=deUnde; i<cifra[poz]; ++i){// pun cifra i
if (i == C){
for(int j=K-1-cnt; j<Cifmax; ++j) Rez += dp[cifra[0]-poz][j];
}else {
for(int j=K-cnt; j<Cifmax; ++j) Rez += dp[cifra[0]-poz][j];
}
}
if (cifra[poz] == C) baga(poz+1, cnt+1, Rez);
else baga(poz+1, cnt, Rez);
}
int rezolva(int X){
if (X < 10 && C <= X) return 1;
if (X < 10) return 0;
// dp[i][j] = numarul de numere de lungime i care au cifra C de j ori
// afla(B) - afla(A-1)
// odata le numar pe alea de lungimea < decat lungimea numarului curent
// iar apoi cand le numar pe alea de lungime = lungimea numarului o sa am nevoie de aceeasi dinamica doar ca in asta nu o sa fiu atent
// la cazul cand primda pun 0
desc(X); // fac un vector cifra[] in care am puse cifrele lui X; iar in cifra[0] = cate cifre are X
int Rez = 0;
faDinamica(1);// cazul cand iau in considerare cazul cu 1
for(int i=1; i<cifra[0]; ++i){
for(int j=K; j<Cifmax; ++j) Rez += dp[i][j];// lungime i si cifra C apare de j ori (j >= K);
}
//cout << Rez << "\n";
faDinamica(0);// cazul cand nu iau in considerare cazul cu 0
// acum le numar pe alea de aceeasi lungime cu X
baga(1, 0, Rez);
//cout << Rez << "\n";
return Rez;
}
int main(){
citeste();
int cazFavor = rezolva(B) - rezolva(A-1);
int cazTotale = B - A + 1;
g << fixed << setprecision(4) << (double)cazFavor / (double)cazTotale << "\n";
//rezolva(B);
f.close();
g.close();
return 0;
}