Cod sursa(job #467155)

Utilizator sodamngoodSo Damn Good sodamngood Data 28 iunie 2010 12:20:12
Problema Pod Scor 15
Compilator cpp Status done
Runda Stelele Informaticii 2010, clasele X-XII, Ziua 2 Marime 4.21 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];
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++) {
         if(i < K) {
              MAT[1][i+1][i] = 1;
         }
         else {
              MAT[1][1][K] = MAT[1][K][K] = 1;
         }
    }
    
    ridicaputere();
    
    //N[1] = 1, N[2] = 1, ..., N[K-1] = 1, N[K] = 2
    /**
    for(i=1; i<K; i++) {
         cout<<1<<" ";
    }
    cout<<2<<" ";
    for(i=K+1; i<=N; i++) {
         //calculez N[i]
         descompune(i - K);
         int rasp = 0;
         for(j=1; j<K; j++) {
              rasp += AUX[j][K];
         }
         rasp += 2 * AUX[K][K];
         cout<<rasp<<" ";
    }
    cout<<endl;
    **/
    
    //calculez N[N]
    if(N < K) {
         fin = 1;
    }
    else if(N == K) {
         fin = 2;
    }
    else {
         descompune(N - K);
         for(j=1; j<K; j++) {
              fin += AUX[j][K];
              fin %= mod;
         }
         fin += 2 * AUX[K][K];
         fin %= mod;
    }
    
    for(i=1; i<=M; i++) {
         if(Lipsa[i] < K) {
              Cit[i] = 1;
         }
         else if(Lipsa[i] == K) {
              Cit[i] = 2;
         }
         else {
              descompune(Lipsa[i] - K);
              for(j=1; j<K; j++) {
                   Cit[i] += AUX[j][K];
                   Cit[i] %= mod;
              }
              Cit[i] += 2 * AUX[K][K];
              Cit[i] %= mod;
         }
    }
    
    for(i=1; i<=M; i++) {
         //procesez Lipsa[i]
         
         for(j=i+1; j<=M; j++) {
              descompune(Lipsa[j] - Lipsa[i] - 2);
              int sl = 0;
              for(k=1; k<K; k++) {
                   sl += AUX[k][K];
                   sl %= mod;
              }
              sl += 2 * AUX[K][K];
              sl %= mod;
              
              //cout<<Lipsa[j] - Lipsa[i] + 1<<": "<<sl<<endl;
              
              Cit[j] -= (sl * Cit[i]) % mod;
              while(Cit[j] < 0) Cit[j] += mod;
         }
         
         descompune(N - Lipsa[i] - 2);
         int sl = 0;
         for(j=1; j<K; j++) {
              sl += AUX[j][K];
              sl %= mod;
         }
         sl += 2 * AUX[K][K];
         sl %= mod;
         
         fin -= (sl * Cit[i]) % mod;
         while(fin < 0) fin += mod;
    }
    
    fprintf(f2, "%d\n", fin % mod);
    fclose(f1); fclose(f2);
    //getch();
    return 0;
}