Cod sursa(job #2243309)

Utilizator Laura_CorneiLaura Maria Cornei Laura_Cornei Data 20 septembrie 2018 11:56:45
Problema Pod Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.58 kb
#include <fstream>
#include <algorithm>
#define mod 9901
using namespace std;
fstream f1("pod.in", ios::in);
fstream f2("pod.out", ios::out);
int n, m, k, poz[1005];
long long dp[30], F[30][2], T[30][30];
void inm(long long a[30][30], long long b[30][30]){

    long long rez[30][30];
    int i,j,l;
    for(i=1; i<=k; i++)
        for(j=1; j<=k; j++)
            {
                rez[i][j]=0;
                for(l=1; l<=k; l++)
                {
                    rez[i][j]+=a[i][l]*b[l][j];
                    rez[i][j]%=mod;
                }
            }
    for(i=1; i<=k; i++)
        for(j=1; j<=k; j++)
            a[i][j]=rez[i][j];
}
void ridica(long long T[30][30], int p){

    long long rez[30][30];
    for(int i=1; i<=k; i++)
        for(int j=1; j<=k; j++)
            if(i==j) rez[i][j]=1;
            else rez[i][j]=0;
    while(p!=0){
        if(p%2==1) inm(rez, T);
        inm(T,T);
        p/=2;
    }
    for(int i=1; i<=k; i++)
        for(int j=1; j<=k; j++)
            T[i][j]=rez[i][j];
}
void inmulteste(long long T[30][30], long long F[30][2]){

    long long rez[30][2];
    int i, j;
    for(i=1; i<=k; i++){
        rez[i][1]=0;
        for(j=1; j<=k; j++){
            rez[i][1]+=T[i][j]*F[j][1];
            rez[i][1]%=mod;
        }
    }
    for(i=1; i<=k; i++)
        F[i][1]=rez[i][1];
}
int main(){

    int i, j, l, putere;
    f1>>n>>m>>k;
    for(i=1; i<=m; i++)
        f1>>poz[i];
    m++; poz[m]=n+1;
    m++; poz[m]=0;
    sort(poz+1, poz+m+1);

    //dp-ultimele k valori, dp[k]-> val de pe pozitia 0/ poz interzise (dp[k]= 1 intial/0 pe urma)
    for(i=1; i<k; i++) dp[i]=0; dp[k]=1;

    for(l=2; l<=m; l++){
        putere=poz[l]-poz[l-1]-1; //nr de el noi care apar
        for(i=1; i<=k; i++)
            F[i][1]=dp[i]; //F-matrice valori intiale
        for(i=1; i<=k; i++)
            for(j=1; j<=k; j++)
                if(i+1==j) T[i][j]=1;
                else T[i][j]=0; //f[i]=f[i-1]+f[i-k]
        T[k][1]=1; T[k][k]=1; //t[k][1]=coeficientul lui f[i-k], t[k][k]=coef lui f[i-1]
        for(i=2; i<k; i++)    //t[k][2..i]=coeficientii lui f[i-k-1]...f[i-2] (=0)
                T[k][i]=0;  //T=matricea de transf (jos contine vectorul de coeficienti din formula)
        ridica(T, putere);  //T=t^putere
        inmulteste(T, F) ;   //F=T*F
        ///F-> f(poz[i]-k+1) ,f(poz[i]-2), f(poz[i]-1)
        ///f(poz[i])=0, fiind scand.lipsa => nodul dp:
        dp[k]=0;
        for(i=1; i<k; i++)
            dp[i]=F[i+1][1];
    }
    f2<<dp[k-1];///=f(n), dp[k]=f(n+1)
    return 0;
}