Cod sursa(job #841142)

Utilizator stoicatheoFlirk Navok stoicatheo Data 23 decembrie 2012 20:27:36
Problema Puteri Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.38 kb
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <bitset>
using namespace std;
 
#define NMAX 100010
 
long long rez = 0;
 
int N, stepmax;
 
int pr[300];
 
int a[NMAX];
int b[NMAX];
int c[NMAX];
int d[NMAX];
 
char am[NMAX];
char bm[NMAX];
char cm[NMAX];
 
bitset <300000> ap;
int kkt[300000];
 
int prim(int x)
{
    int i;
 
    for (i = 2; i * i <= x; i++)
        if (x % i == 0) return 0;
 
return 1;
}
 
inline int srch(int q)
{
    int step = stepmax, x = 0;
 
    for (; step; step >>= 1)
        if (x + step <= N && d[x + step] <= q)
            x += step;
     
return x;
}
 
long long numar(int x)
{
    // numar cate perechi dau toate alea divizibile la x
 
    int i;
 
    long long rez = 0;
 
    ap = 0;
 
    for (i = 1; i <= N; i++) {
//      if (x > a[i]) am[i] = a[i]; else am[i] = a[i] % x; 
//      if (x > b[i]) bm[i] = b[i]; else bm[i] = b[i] % x; 
//      if (x > c[i]) cm[i] = c[i]; else cm[i] = c[i] % x;
        am[i] = a[i]; while (am[i] >= x) am[i] -= x;
        bm[i] = b[i]; while (bm[i] >= x) bm[i] -= x;
        cm[i] = c[i]; while (cm[i] >= x) cm[i] -= x;
         
        d[i] = (am[i] * 4225) + (bm[i] * 65) + cm[i] % x;
        if ((2 * a[i]) % x == 0 && (2 * b[i] % x == 0) && (2 * c[i] % x == 0)) rez--;
//      if ( (am[i] + am[i] == x || am[i] + am[i] == 2 * x) && (bm[i] + bm[i] == x || bm[i] + bm[i] == 2 * x) && (cm[i] + cm[i] == x || cm[i] + cm[i] == 2 * x)) rez--;
 
        if (!ap[d[i]]) kkt[d[i]] = 0;
        kkt[d[i]]++;
        ap[d[i]] = 1;
    }
 
//  sort(d + 1, d + N + 1);
 
    int aa, bb, cc, nnr;
 
    for (i = 1; i <= N; i++) {
        aa = x - am[i]; if (aa == x) aa = 0;
        bb = x - bm[i]; if (bb == x) bb = 0;
        cc = x - cm[i]; if (cc == x) cc = 0;
 
        if (aa > 64 || bb > 64 || cc > 64) continue;
 
        nnr = (aa * 4225) + (bb * 65) + cc;
 
        if (!ap[nnr]) continue;
 
        rez += kkt[nnr];
    }
 
    return (rez >> 1);
}
 
void back(int k, int last, int nr)
{
    if (nr != 1) {
        if (k & 1) rez += numar(nr);
        else rez -= numar(nr);
    }
 
    int i;
    for (i = last + 1; i <= pr[0]; i++) 
        if (nr * pr[i] <= 128) back(k + 1, i, nr * pr[i]);
}
 
int gen(int N)
{
    freopen("puteri.in", "w", stdout);
     
    printf("%d\n", N);
 
    int i;
    for (i = 1; i <= N; i++) printf("%d %d %d\n", rand() % 64, rand() % 64, rand() % 64);
fclose(stdout);
return 0;
}
 
int cmmdc(int a, int b)
{
    if (a == 0) return b;
    if (b == 0) return a;
    return cmmdc(b, a % b);
}
 
void get_brute()
{
    int i, j, aa, bb, cc, rez = 0;
 
    for (i = 1; i <= N; i++)
        for (j = i + 1; j <= N; j++) {
            aa = a[i] + a[j]; bb = b[i] + b[j]; cc = c[i] + c[j];
            if (cmmdc(cmmdc(aa, bb), cc) != 1) rez++;
        }
 
    printf("%d\n", rez);
}
 
int main()
{
//  gen(100000);
     
    int i;
     
    freopen("puteri.in", "r", stdin);
    freopen("puteri.out", "w", stdout);
 
    for (i = 2; i <= 128; i++) if (prim(i)) pr[++pr[0]] = i;
     
    scanf("%d", &N);
 
    for (stepmax = 1; stepmax <= N; stepmax <<= 1); stepmax >>= 1;
 
    for (i = 1; i <= N; i++) scanf("%d %d %d", &a[i], &b[i], &c[i]);
 
    back(0, 0, 1);
 
    printf("%lld\n", rez);
 
//  get_brute();
 
fclose(stdin);
fclose(stdout);
return 0;
}