Cod sursa(job #350601)

Utilizator slayerdmeMihai Dumitrescu slayerdme Data 24 septembrie 2009 23:09:39
Problema Divk Scor 90
Compilator c Status done
Runda Arhiva de probleme Marime 3.06 kb
#include <stdio.h>
#include <stdlib.h>

#define NMAX 500001
#define KMAX 100001

/** Returns the position of the smallest entry larger or equal to query after pos in an ordered array. Return length if none found
/** Pos has to be >= 0. Array entries should not repeat. **/
int lognsearch(int *array, int lenght, int pos, int query) {
    int i = pos, multi = 1;
    while (i < lenght && array[i] < query) {
        if (i + multi < lenght && array[i + multi] < query) {
            i = i + multi;
            multi = multi * 2;
        } else if (multi > 1) {
            multi = multi / 2;
        } else {
            i++;
            break;
        }
    }
    return i;
}

int main() {
    int n, a, b, k;
    int i, j, x, sum;
    int sums[NMAX + 1];
    int repeats[KMAX];
    int repeatsum[KMAX];
    int allpositions[NMAX + 1];

    int *positions;

    FILE *fin;
    FILE *fout;


    fin = fopen("divk.in", "r");
    fout = fopen("divk.out", "w");
    fscanf(fin, "%d", &n);
    fscanf(fin, "%d", &k);
    fscanf(fin, "%d", &a);
    fscanf(fin, "%d", &b);


    /* Prepare for counting - reorder by position */
    sum = 0;
    for (i = 0; i < n; i++) {
        fscanf(fin, "%d", &x);
        sums[i] = sum;
        repeats[sum]++;
        sum += x;
        sum = sum % k;
    }
    sums[n] = sum;
    repeats[sum]++;

    fclose(fin);

    sum = 0;
    for (i = 0; i < k; i++) {
        repeatsum[i] = sum;
        sum += repeats[i];
    }

    for (i = 0; i <= n; i++) {
        allpositions[repeatsum[sums[i]]] = i;
        repeatsum[sums[i]]++;
    }

    //Restore repeats
    sum = 0;
    for (i = 0; i < k; i++) {
        repeatsum[i] = sum;
        sum += repeats[i];
    }



    /* Count all substrings */
    int divk = 0;
    int asearch, bsearch;
    int t;

    //debug
//    printf("%d\n", lognsearch(repeatsum, k, 3, 0));
//    for (i = 0; i < k; i ++) {
//        printf("%d\n", repeatsum[i]);
//    }
//    printf("end repeatsum\n");
//    for (i = 0; i <= n; i++) {
//        printf("%d\n", sums[i]);
//    }
//    printf("end sums\n");
//    for (i = 0; i <= n; i ++) {
//        printf("%d\n", allpositions[i]);
//    }
//    printf("end allpositions\n");
    //enddebug

    for (i = 0; i < k; i++)
        if (repeats[i] > 1) {
            j = repeats[i];
            positions = allpositions + repeatsum[i];

            //debug
//            printf("%d ", i);
//            printf("%d next\n", repeats[i]);
//            for (t = 0; t < j; t++) {
//                printf("%d ", positions[t]);
//            }
//            printf("blah\n");
            //enddebug

            for (t = 0; t < j - 1; t++) {
                asearch = lognsearch(positions, j, t, positions[t] + a);
                bsearch = lognsearch(positions, j, t, positions[t] + b + 1);

                //debug
//                printf("search %d %d %d %d\n", repeats[i], t, positions[t] + a, positions[t] + b);
//                printf("searchk %d %d %d\n", asearch, bsearch, divk);
                //enddebug

                divk += bsearch - asearch;
            }
        }
    fprintf(fout, "%d\n", divk);
    return 0;
}