Cod sursa(job #922372)

Utilizator vendettaSalajan Razvan vendetta Data 22 martie 2013 09:34:29
Problema Oite Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.19 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

ifstream f("oite.in");
ofstream g("oite.out");
#define nmax 1024
#define Lmax 1000005
#define MOD 666013

int n, L, a[nmax];
typedef vector< pair<int,int> >::iterator it;
vector< pair<int,int> > lista[MOD+4];
int dp[3][5][Lmax];

void citeste(){
    f >> n >> L;
    for(int i=1; i<=n; ++i) f >> a[i];
}

void baga(int val, int poz){
    int rest = val % MOD;
    lista[rest].push_back( make_pair( val, poz) );
}

void bagaHash(){
    for(int i=1; i<=n; ++i){
        for(int j=i+1; j<=n; ++j){
            baga(a[i]+a[j], i);
        }
    }
}

inline int cauta(int Val, int poz){
    if (Val > L) return 0;
    int rest = Val % MOD;
    int cnt = 0;
    for(it i=lista[rest].begin(); i!=lista[rest].end(); i++){
        if( (*i).first == Val && (*i).second > poz ){
            ++cnt;
        }
    }
    return cnt;
}

void init(int linie){
    for(int j=1; j<=4; ++j){
        for(int k=0; k<=L; ++k) dp[linie][j][k] = 0;
    }
}

void bagaDinamica(){
    // dp[i][j][L] = nr de siruri cu suma L ce se termina sau nu se termina pe i si are j termeni
    int linie = 1;
    dp[1-linie][1][ a[1] ] = 1;
    for(int i=2; i<=n; ++i){
        init(linie);
        for(int j=1; j<=4; ++j){
            for(int k=0; k<=L; ++k){
                dp[linie][j][k] += dp[1^linie][j][k];
                if ( j < 4 ) {
                    int newK = k + a[i];
                    if (newK > L) continue;
                    dp[linie][j+1][newK] += dp[1^linie][j][k];
                }
            }
        }
        linie = 1^ linie;
    }
    g << dp[1^linie][4][L] << "\n";
}

void rezolva(){
    // bag fiecare pereche i, j i<j intr-un hash; apoi vin cu fiecare pereche si caut suma
    // in hash
    if (L <= 1000000){
        bagaDinamica();
        return;
    }
    bagaHash();

    int rez =0;
    for(int i=1; i<=n; ++i){
        for(int j=i+1; j<=n; ++j){
            rez += cauta(L - (a[i] + a[j]), j );
        }
    }
    cout << rez << "\n";
    g << rez << "\n";
}

int main(){
    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;
}