Cod sursa(job #842028)

Utilizator enedumitruene dumitru enedumitru Data 25 decembrie 2012 21:23:57
Problema Diviz Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.53 kb
/*  Problema se rezolva prin metoda programarii dinamice.
    Fie P[j][i][r] numarul de moduri de a alege subsiruri distincte de lungime j care contin ca ultima cifra cea de-a i-a cifra a numarului N,
    subsiruri care sa dea restul r la impartirea K. Daca ne aflam in starea (j, i, r) putem sa actualizam starea (j+1, first[cif][i+1], (r*10+cif) mod K),
    considerand ca am adaugat la sfarsitul fiecarui subsir definit de (j, i, r) cifra cif. Prin first[cif][i] se defineste prima aparitie in numarul N a cifrei cif dupa pozitia i. Tabloul first va fi, evident, preprocesat. Pentru a nu numara subsirurile egale de doua ori, trebuie sa initializam pentru lungimea 1 doar pozitiile care contin pentru prima oara o cifra. Astfel initializam starile (1, first[cif][0], cif mod K) cu 1, pentru cif = 1..9 (ca nu cumva un subsir sa inceapa cu 0). Pe parcurs, adunam la solutie starile care au lungimea cuprinsa intre A si B si care au r egal cu 0.
    Complexitatea finala a algoritmului este O(K * L2), unde L este numarul de cifre ale numarului N.
*/
#include <cstring>
#include <fstream>
using namespace std;
ifstream f("diviz.in"); ofstream g("diviz.out");
const int MOD = 30103;
int K, A, B, nr;
char N[202];
int P[2][202][102];
int last[10],x[202];
int main()
{
    f >> K >> A >> B >> N;
    int M = strlen(N);
    for (int i = 1; i <= M; ++i) x[i]=N[i-1]-'0';
    int act = 0;
    for (int i = 1; i <= M; ++i) // cu i cifre
    {
        act = !act;
        memset(P[act], 0, sizeof(P[act]));
        for (int j = 1; j <= M; ++j) // se termina pana in j
        {
            if (i == 1 && x[j]) P[act][j][x[j] % K] = 1;
            for (int r = 0; r < K; ++r) // cel dinainte avea restul r
            {
                P[act][j][(r * 10 + x[j]) % K] += P[!act][j - 1][r];
                if (P[act][j][(r * 10 + x[j]) % K] >= MOD) P[act][j][(r * 10 + x[j]) % K] -= MOD;
            }
        }
        for (int r = 0; r < K; ++r)
        {
            memset(last, 0, sizeof(last));
            for (int j = 1; j <= M; ++j)
            {
                P[act][j][r] -= last[x[j]];
                last[x[j]] = P[act][j][r] + last[x[j]];
                P[act][j][r] += P[act][j - 1][r];
                while (P[act][j][r] >= MOD) P[act][j][r] -= MOD;
                while (P[act][j][r] < 0)    P[act][j][r] += MOD;
            }
        }
        if (i >= A && i <= B)
        {
            nr += P[act][M][0];
            if (nr >= MOD) nr -= MOD;
        }
    }
    g << nr << '\n';
    g.close();
    return 0;
}