Cod sursa(job #872239)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 5 februarie 2013 21:46:44
Problema Pod Scor 95
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.63 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],C[maxk][maxk];
int last[maxk],now[maxk],D[maxk*maxm<<1],st,dr;

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;
}