Cod sursa(job #467413)

Utilizator vladiiIonescu Vlad vladii Data 28 iunie 2010 20:23:43
Problema Pod Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.64 kb
#include <iostream>
//#include <conio.h>
using namespace std;
#define mmax 1010
#define mod 9901
#define log2N 31

int N, M, K, fin;
int Lipsa[mmax], Cit[mmax], Ni[21], Nv[21];
int MAT[log2N][21][21], AUX[21][21], AUX2[21][21];

void ridicaputere() {
    int i, j, k, p, put = 2;
    while((1 << (put - 1)) <= N) {
         p = put - 1;
         for(k=1; k<=K; k++) {
              for(i=1; i<=K; i++) {
                   for(j=1; j<=K; j++) {
                        MAT[put][i][j] += (MAT[p][i][k] * MAT[p][k][j]) % mod;
                        MAT[put][i][j] %= mod;
                   }
              }
         }
         put++;
    }
}

void descompune(int val) {
    int i, j, k, p = 1;
    for(i=1; i<=K; i++) {
         memset(AUX[i], 0, sizeof(AUX[i]));
    }
    for(i=1; i<=K; i++) {
         AUX[i][i] = 1;
    }
    
    while(val) {
         if(val % 2) {
              //AUX = AUX * MAT[pos]
              for(i=1; i<=K; i++) {
                   for(j=1; j<=K; j++) {
                        AUX2[i][j] = 0;
                   }
              }
              for(k=1; k<=K; k++) {
                   for(i=1; i<=K; i++) {
                        for(j=1; j<=K; j++) {
                             AUX2[i][j] += (AUX[i][k] * MAT[p][k][j]) % mod;
                             AUX2[i][j] %= mod;
                        }
                   }
              }
              for(i=1; i<=K; i++) {   
                   for(j=1; j<=K; j++) {
                        AUX[i][j] = AUX2[i][j];
                   }
              }
         }
         val = val/2;
         p++;
    }
}     

int main() {
    FILE *f1=fopen("pod.in", "r"), *f2=fopen("pod.out", "w");
    int i, j, p, q, k;
    
    fscanf(f1, "%d %d %d\n", &N, &M, &K);
    for(i=1; i<=M; i++) {
         fscanf(f1, "%d", &Lipsa[i]);
    }
    
    sort(Lipsa+1, Lipsa+M+1);
    
    for(i=1; i<=K; i++) {
         MAT[0][i][i] = 1;
         if(i < K) {
              MAT[1][i+1][i] = 1;
         }
         else {
              MAT[1][1][K] = MAT[1][K][K] = 1;
         }
    }
    
    ridicaputere();
    
    int last = 0, pos = 1;
    Ni[0] = 1;
    for(i=1; i<=K; i++) {
         if(Lipsa[pos] == i) {
              Ni[i] = 0;
              pos++;
         }
         else {
              if(i-K >= 0) {
                   Ni[i] = Ni[i-1] + Ni[i-K];
              }
              else {
                   Ni[i] = Ni[i-1];
              }
         }
    }
    
    int sc = 1, ok = 1;
    last = K;

    while(ok) {
         if(pos <= M) {
              sc = Lipsa[pos];
              //aplic pe intervalul [last, sc - 1]
              //N[sc] = 0;
              descompune(sc - last);
              for(i=1; i<K; i++) {
                   Nv[i] = 0;
                   for(j=1; j<=K; j++) {
                        Nv[i] += (Ni[j] * AUX[j][i]) % mod;
                        Nv[i] %= mod;
                   }
              }
              for(i=1; i<K; i++) {
                   Ni[i] = Nv[i];
              }
              Ni[K] = 0;
              pos++;
              last = sc;
         } 
         else {
              descompune(N - last);
              for(i=1; i<=K; i++) {
                   Nv[i] = 0;
                   for(j=1; j<=K; j++) {
                        Nv[i] += (Ni[j] * AUX[j][i]) % mod;
                        Nv[i] %= mod;
                   }
              }
              fin = Nv[K];
              ok = 0;
         }
    }
    
    if(Lipsa[M] == N) fprintf(f2, "0\n");
    else fprintf(f2, "%d\n", fin % mod);
    fclose(f1); fclose(f2);
    //getch();
    return 0;
}