Cod sursa(job #779417)

Utilizator vendettaSalajan Razvan vendetta Data 17 august 2012 17:22:58
Problema Diviz Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.3 kb
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>

using namespace std;

#define nmax 201
#define Kmax 101
#define MOD 30103

ifstream f("diviz.in");
ofstream g("diviz.out");

int K, A, B, n, a[nmax], unde[nmax][11];
int dp[2][nmax][Kmax];

void citeste(){

   f>>K>>A>>B;
   f.get();
   string s;
   getline(f,s);
   for(int i=0; i<s.size(); i++) a[i+1] = s[i]-'0';
   n = s.size();

}

void sterge(int a[Kmax]){

   for(int i=0; i<K; i++) a[i] = 0;

}

void rezolva(){

   //nr de numerere cu cifre intre A si B si care sa fie divizibile cu K
   //dp[i][j][r] = nr de subsiruri din primele i iar a[i] sa fi a j-a cifra din numar si acel numar sa dea restul r
   //imi precalculez unde[i][cifra] = poz; prima pozitie a lui cifra din dreapta lui i
   //pt ca ma intereseaza cand sunt in starea i,j,r sa ma duc in dreapta dar doar la prima cifra din fiecare 0,9 din dreapta lui i

   for(int i=n; i>=1; i--){
      for(int j=0; j<=9; j++){
         unde[i][j] = unde[i+1][j];
      }
      unde[i][a[i]] = i;
   }
   //initializez dinamica : initializez fiecare prima cifra (cifra = 1..9)

   for(int i=1; i<10; i++) if (unde[1][i]!=0)dp[1][ unde[1][i] ][i%K] = 1;;//prima cifra din stanga lui 1, evident ma intereseaza prima aparitie a fiecarei cifre

   int rez = 0;
   int linie = 1;
   //intorc dinamica

   for(int j=1; j<=B; j++){
      if (j>=A)
         for(int i=1; i<=n; i++){
            rez += (dp[linie][i][0]);
            if (rez >=MOD) rez -=MOD;
         }
      for(int i=1; i<=n; i++)
        sterge(dp[1-linie][i]);
      for(int i=1; i<=n; i++){
         for(int r=0; r<K; r++){//ma aflu in (i,j,r) ma duc in unde[i+1][cifra], j+1, (r*10+cifra)%K
            if (dp[linie][i][r] == 0) continue;//if-ul asta face diff dintre 50 si 100...
            for(int cifra = 0; cifra<10; cifra++){
               if (unde[i+1][cifra] == 0) continue;
               dp[1-linie][ unde[i+1][cifra] ][(r*10+cifra)%K] += dp[linie][i][r];
               if (dp[1-linie][ unde[i+1][cifra] ][(r*10+cifra)%K] >=MOD)
                  dp[1-linie][ unde[i+1][cifra] ][(r*10+cifra)%K] -= MOD;
            }
         }
      }

      linie = 1-linie;

   }

   g << rez << "\n";

}

int main(){


   citeste();
   rezolva();

   return 0;


}