Cod sursa(job #467102)

Utilizator sodamngoodSo Damn Good sodamngood Data 28 iunie 2010 11:32:14
Problema Pod Scor 5
Compilator cpp Status done
Runda Stelele Informaticii 2010, clasele X-XII, Ziua 2 Marime 3.17 kb
#include <iostream>
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][3][3], AUX[3][3], AUX2[3][3];

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

void descompune(int val) {
    int i, j, p = 1;
    for(i=1; i<=2; i++) {
         memset(AUX[i], 0, sizeof(AUX[i]));
    }
    AUX[1][1] = AUX[2][2] = 1;
    
    while(val) {
         if(val % 2) {
              //AUX = AUX * MAT[pos]      
              AUX2[1][1] = (AUX[1][1] * MAT[p][1][1] + AUX[1][2] * MAT[p][2][1]) % mod;
              AUX2[1][2] = (AUX[1][1] * MAT[p][1][2] + AUX[1][2] * MAT[p][2][2]) % mod;
              AUX2[2][1] = (AUX[2][1] * MAT[p][1][1] + AUX[2][2] * MAT[p][2][1]) % mod;
              AUX2[2][2] = (AUX[2][1] * MAT[p][1][2] + AUX[2][2] * MAT[p][2][2]) % mod;
              for(i=1; i<=2; i++) {   
                   for(j=1; j<=2; 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;
    
    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);
    
    MAT[1][1][1] = 0; MAT[1][1][2] = 1;
    MAT[1][2][1] = 1; MAT[1][2][2] = 1;
    
    ridicaputere();
    
    /**
    //N[1] = 1, N[2] = 1, ..., N[K-1] = 1, N[K] = 2
    for(i=K+1; i<=N; i++) {
         //calculez N[i]
         descompune(i - K);
         cout<<1 * AUX[1][2] + 2 * AUX[2][2]<<endl<<endl;
    }
    **/
    
    //calculez N[N]
    if(N < K) {
         fin = 1;
    }
    else if(N == K) {
         fin = 2;
    }
    else {
         descompune(N - K);
         fin = (AUX[1][2] + 2 * AUX[2][2]) % 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);
              Cit[i] = (AUX[1][2] + 2 * AUX[2][2]) % mod;
         }
    }
    
    for(i=1; i<=M; i++) {
         //procesez Lipsa[i]
         //i = primul termen fibonacci
         for(j=i+1; j<=M; j++) {
              descompune(Lipsa[j] - Lipsa[i] + 2);
              int sl = AUX[1][1];
              Cit[j] -= (sl * Cit[i]) % mod;
              while(Cit[j] < 0) Cit[j] += mod;
         }
         descompune(N - Lipsa[i] + 2);
         int sl = AUX[1][1];
         fin -= (sl * Cit[i]) % mod;
         while(fin < 0) fin += mod;
    }
    
    fprintf(f2, "%d\n", fin % mod);
    fclose(f1); fclose(f2);
    return 0;
}