Cod sursa(job #876021)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 11 februarie 2013 08:51:11
Problema Pod Scor 95
Compilator cpp Status done
Runda Arhiva de probleme Marime 3 kb
#include<stdio.h>
#include<cstring>
#include<algorithm>
  
#define maxm 1005
#define maxk 23
#define mod 9901
  
using namespace std;
  
FILE*f=fopen("pod.in","r");
FILE*g=fopen("pod.out","w");
  
int n,m,k;
int p[maxm],M[maxk][maxk],aux[maxk][maxk],S[maxk][maxk],P[maxk][maxk];
int last[maxk],now[maxk],D[maxk*maxm<<1],st,dr;
unsigned int C[maxk][maxk];

inline void mult ( int (*A)[maxk] , int B[maxk][maxk] ){
	
    for ( int aux = 1 ; aux <= k ; ++aux ){
        for ( int i = 1 ; i <= k ; ++i ){
            for ( int j = 1 ; j <= k ; ++j ){
                  
               C[i][j] = (C[i][j] + A[i][aux]*B[aux][j]);
            }
        }
    }
      
    for ( int i = 1 ; i <= k ; ++i ){
        for ( int j = 1 ; j <= k ; ++j ){
            A[i][j] = C[i][j]%mod;
            C[i][j] = 0;
        }
    }
}
  
inline void lgpow ( int (*A)[maxk] , int b ){
    memset(S,0,sizeof(S));
    for ( int i = 1 ; i <= k ; ++i ) S[i][i] = 1;
    memcpy(P,A,sizeof(P));
     
    while ( b ){
        if ( b & 1 ){
            mult(S,P);
        }
          
        mult(P,P);
        b >>= 1;
    }
      
    memcpy(A,S,sizeof(S));
}
 
int main () {
      
    fscanf(f,"%d %d %d",&n,&m,&k);
    for ( int i = 1 ; i <= m ; ++i ){
        fscanf(f,"%d",&p[i]);
    }
     
    int sol = -1;
    if ( p[m] == n )    sol = 0;
     
    sort(p+1,p+m+1); p[++m] = n;
    M[1][1] = M[1][k] = 1;
    for ( int i = 2 ; i <= k ; ++i ) M[i][i-1] = 1;
     
    int from = 0; last[0] = 1; dr = -1;
    for ( int i = 1 ; i <= m && sol == -1 ; ++i ){
          
        memcpy(aux,M,sizeof(M));
        lgpow(aux,p[i]-from);
         
        for ( int j = 0 ; j < k ; ++j ){
            now[j] = 0;
             
            for ( int x = 1 ; x <= k ; ++x ){
                now[j] = (now[j] + aux[j+1][x]*last[x-1])%mod;
            }
        }
         
        if ( i == m ){
            sol = now[0];
            break ;
        }
         
        st = dr+1;
        for ( int j = k-1 ; j > 0 ; --j ){
            D[++dr] = now[j];
        }
        D[++dr] = 0;
                 
        int ultima = p[i],acum = p[i],next = i+1;
        do{
            ++acum;
            if ( p[next] == acum ){
                ultima = p[next];
                ++next; D[++dr] = 0; ++i;
                if ( acum == n ){
                    sol = D[st] + D[dr-1]; if ( sol >= mod ) sol -= mod;
                    break ;
                }
            }
            else{
                ++dr;
                D[dr] = D[st] + D[dr-1]; if ( D[dr] >= mod ) D[dr] -= mod;
                if ( acum == n ){
                    sol = D[dr]; break ;
                }
            }
            ++st;
        }while ( acum-ultima < k && sol == -1 );
         
        for ( int i = 0 ; i < k ; ++i ){
            last[k-i-1] = D[st+i];
        }
        from = acum;
    }
     
    fprintf(g,"%d\n",sol);
      
    fclose(f);
    fclose(g);
      
    return 0;
}