Cod sursa(job #594938)

Utilizator SpiderManSimoiu Robert SpiderMan Data 10 iunie 2011 16:20:37
Problema Puteri Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.5 kb
# include <cstdio>
# include <cstring>

const char *FIN = "puteri.in", *FOU = "puteri.out" ;
const int MAX = 65, hg = 1 << 13;

unsigned char V[1 << 17];
int N, poz, cnt[MAX][MAX][MAX], CNT[MAX][MAX][MAX], prim[MAX << 1], st[MAX << 1] ;
long long solution ;

# define verf ++poz == hg ? fread ( ch, 1, hg, stdin ), poz = 0 : 0
char ch[ hg ] ;

inline void cit ( int &x ) {
    if ( ch[0] == '\0' ) fread ( ch, 1, hg, stdin ) ;
    else for ( ; ch[poz] < '0' || ch[poz] > '9' ; verf ) ;
    for ( x = 0 ; ch[poz] >= '0' && ch[poz] <= '9' ; x = x * 10 + ch[poz] - '0', verf ) ;
}

void rec (int lev, int K, int pr, int see) {
    if (pr > (MAX << 1) - 2) return ;
    if (lev == K) {
        memset (CNT, 0, sizeof (CNT));
        for (int a = 0; a < MAX; ++a) {
            for (int b = 0; b < MAX; ++b) {
                for (int c = 0; c < MAX; ++c) {
                    CNT[a % pr][b % pr][c % pr] += cnt[a][b][c];
                }
            }
        }
        for (int a = 0; a < MAX && a < pr; ++a) {
            for (int b = 0; b < MAX && b < pr; ++b) {
                for (int c = 0; c < MAX && c < pr; ++c) {
                    int A = (pr - a) % pr, B = (pr - b) % pr, C = (pr - c) % pr;
                    if (A > MAX - 1 || B > MAX - 1 || C > MAX - 1) continue ;
                    solution += see * 1LL * CNT[a][b][c] * (CNT[A][B][C] - (a == A && b == B && c == C));
                }
            }
        }
        return ;
    }
    for (int i = (lev > 0 ? st[lev - 1] + 1 : 1); i <= prim[0]; ++i) {
        st[lev] = i;
        rec (lev + 1, K, pr * prim[i], see) ;
    }
}

int main (void) {
    freopen (FIN, "r", stdin) ;

    scanf ("%d", &N) ;
    for (int i = 0, a, b, c; i < N; ++i) {
        scanf ("%d %d %d", &a, &b, &c);
        ++cnt[a][b][c];
    }

    for (int i = 1; ( i * i << 1 ) + ( i << 1 ) <= MAX << 1; ++i) {
        if ( ( V[i >> 3] & ( 1 << ( i & 7 ) ) ) == 0 ) {
            for (int j = ( i * i << 1 ) + ( i << 1 ); ( j << 1 ) + 1 <= MAX << 1; j += ( i << 1 ) + 1)
                V[j >> 3] |= ( 1 << ( j & 7 ) );
        }

    }
    prim[++prim[0]] = 2;
    for (int i = 1; ( i << 1 ) + 1 <= MAX << 1; ++i) {
        if ( ( V[i >> 3] & ( 1 << ( i & 7 ) ) ) == 0 )
            prim[++prim[0]] = (i << 1) + 1;
    }
    for (int i = 1, pr = 1; i <= prim[0]; ++i) {
        pr *= prim[i];
        if (pr > (MAX << 1) - 2) break ;
        rec (0, i, 1, (i & 1 ? 1 : -1)) ;
    }
    fprintf (fopen (FOU, "w"), "%lld", solution >> 1) ;
}