天天看點

GCJ09_ACRush_A題

GCJ頁面:

http://code.google.com/intl/zh-CN/codejam/

#include <vector>

#include <list>

#include <map>

#include <set>

#include <deque>

#include <queue>

#include <stack>

#include <bitset>

#include <algorithm>

#include <functional>

#include <numeric>

#include <utility>

#include <sstream>

#include <iostream>

#include <iomanip>

#include <cstdio>

#include <cmath>

#include <cstdlib>

#include <cctype>

#include <string>

#include <cstring>

#include <cstdio>

#include <cmath>

#include <cstdlib>

#include <ctime>

using namespace std;

#define SIZE(X) ((int)(X.size()))//NOTES:SIZE(

#define LENGTH(X) ((int)(X.length()))//NOTES:LENGTH(

#define MP(X,Y) make_pair(X,Y)//NOTES:MP(

const int maxlength=200;

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

class bigint

{

public:

int oper,length,a[maxlength];

bigint(int=0);

~bigint();

int max(int a,int b);

void check();

void operator=(bigint m);

void operator=(int m);

void operator=(char *s);

bool operator<(bigint m);

bool operator<=(bigint m);

bool operator>(bigint m);

bool operator>=(bigint m);

bool operator==(bigint m);

bool operator!=(bigint m);

bigint operator-();

bigint operator+(bigint m);

void operator+=(bigint m);

bigint operator-(bigint m);

void operator-=(bigint m);

bigint operator*(bigint m);

bigint operator*(int m);

void operator*=(bigint m);

void operator*=(int m);

bigint operator/(bigint m);

bigint operator/(int m);

void operator/=(bigint m);

void operator/=(int m);

bigint operator%(bigint m);

bigint operator%(int m);

void operator%=(bigint m);

void operator%=(int m);

};

bigint abs(bigint m);

bool read(bigint &m);

void write(bigint m);

void swrite(char *s,bigint m);

void writeln(bigint m);

bigint sqr(bigint m);

bigint sqrt(bigint m);

bigint gcd(bigint a,bigint b);

bigint lcm(bigint a,bigint b);

int bigint::max(int a,int b)

{

return (a>b)?a:b;

}

bigint::bigint(int v)

{

(*this)=v;

this->check();

}

bigint::~bigint()

{

}

void bigint::check()

{

for (;length>0 && a[length]==0;length--);

if (length==0)

oper=1;

}

void bigint::operator=(bigint m)

{

oper=m.oper;

length=m.length;

memcpy(a,m.a,maxlength*sizeof(int));

this->check();

}

void bigint::operator=(int m)

{

oper=(m>0)?1:-1;

m=abs(m);

memset(a,0,maxlength*sizeof(int));

for (length=0;m>0;m=m/10000)

a[++length]=m%10000;

this->check();

}

void bigint::operator=(char *s)

{

int i,L;

(*this)=0;

if (s[0]=='-' || s[0]=='+')

{

if (s[0]=='-')

oper=-1;

L=strlen(s);

for (i=0;i<L;i++)

s[i]=s[i+1];

}

L=strlen(s);

length=(L+3)/4;

for (i=0;i<L;i++)

a[(L-i+3)/4]=a[(L-i+3)/4]*10+(s[i]-48);

this->check();

}

bool bigint::operator<(bigint m)

{

if (oper!=m.oper)

return oper<m.oper;

if (length!=m.length)

return oper*length<m.length*oper;

for (int i=length;i>=1;i--)

if (a[i]!=m.a[i])

return a[i]*oper<m.a[i]*oper;

return false;

}

bool bigint::operator<=(bigint m)

{

return !(m<(*this));

}

bool bigint::operator>(bigint m)

{

return m<(*this);

}

bool bigint::operator>=(bigint m)

{

return !((*this)<m);

}

bool bigint::operator==(bigint m)

{

return (!((*this)<m)) && (!(m<(*this)));

}

bool bigint::operator!=(bigint m)

{

return ((*this)<m) || (m<(*this));

}

bigint bigint::operator-()

{

bigint c=(*this);

c.oper=-c.oper;

c.check();

return c;

}

bigint abs(bigint m)

{

bigint c=m;

c.oper=abs(c.oper);

c.check();

return c;

}

bigint bigint::operator+(bigint m)

{

if (m.length==0)

return (*this);

if (length==0)

return m;

if (oper==m.oper)

{

bigint c;

c.oper=oper;

c.length=max(length,m.length)+1;

for (int i=1,temp=0;i<=c.length;i++)

c.a[i]=(temp=(temp/10000+a[i]+m.a[i]))%10000;

c.check();

return c;

}

return (*this)-(-m);

}

bigint bigint::operator-(bigint m)

{

if (m.length==0)

return (*this);

if (length==0)

return (-m);

if (oper==m.oper)

{

bigint c;

if (abs(*this)>=abs(m))

{

c.oper=oper;

c.length=length;

for (int i=1,temp=0;i<=length;i++)

c.a[i]=((temp=(-int(temp<0)+a[i]-m.a[i]))+10000)%10000;

c.check();

return c;

}

return -(m-(*this));

}

return (*this)+(-m);

}

bool read(bigint &m)

{

char s[maxlength*4+10];

if (scanf("%s",&s)==-1)

return false;

for (int i=0;s[i];i++)

if (!(s[i]>='0' && s[i]<='9' || (s[i]=='+' || s[i]=='-') && i==0))

return false;

m=s;

return true;

}

void swrite(char *s,bigint m)

{

int L=0;

if (m.oper==-1)

s[L++]='-';

sprintf(s+L,"%d",m.a[m.length]);

for (;s[L]!=0;L++);

for (int i=m.length-1;i>=1;i--)

{

sprintf(s+L,"%04d",m.a[i]);

L+=4;

}

s[L]=0;

}

void write(bigint m)

{

if (m.oper==-1)

printf("-");

printf("%d",m.a[m.length]);

for (int i=m.length-1;i>=1;i--)

printf("%04d",m.a[i]);

}

void writeln(bigint m)

{

write(m);

printf("/n");

}

bigint bigint::operator*(bigint m)

{

bigint c;

c.oper=oper*m.oper;

c.length=length+m.length;

for (int i=1;i<=m.length;i++)

{

int number=m.a[i],j,temp=0;

for (j=1;j<=length;j++)

c.a[i+j-1]+=number*a[j];

if (i%10==0 || i==m.length)

for (j=1;j<=c.length;j++)

c.a[j]=(temp=(temp/10000)+c.a[j])%10000;

}

c.check();

return c;

}

bigint bigint::operator*(int m)

{

if (m<0)

return -((*this)*(-m));

if (m>100000)

return (*this)*bigint(m);

bigint c;

c.length=length+2;

c.oper=oper;

int t=0;

for (int i=1;i<=c.length;i++)

c.a[i]=(t=(t/10000+a[i]*m))%10000;

c.check();

return c;

}

bigint bigint::operator/(bigint m)

{

if (m.length==0)

{

printf("Division by zero./n");

exit(0);

}

if (abs(*this)<abs(m))

return 0;

bigint c,left;

c.oper=oper/m.oper;

m.oper=1;

c.length=length-m.length+1;

left.length=m.length-1;

memcpy(left.a+1,a+length-left.length+1,left.length*sizeof(int));

for (int i=c.length;i>=1;i--)

{

left=left*10000+a[i];

int head=0,tail=10000,mid;

while (head+1<tail)

{

mid=(head+tail)/2;

if (m*mid<=left)

head=mid;

else

tail=mid;

}

c.a[i]=head;

left-=m*head;

}

c.check();

return c;

}

bigint bigint::operator/(int m)

{

if (m<0)

return -((*this)/(-m));

if (m>100000)

return (*this)/bigint(m);

bigint c;

c.oper=oper;

c.length=length;

int t=0;

for (int i=c.length;i>=1;i--)

c.a[i]=(t=(t%m*10000+a[i]))/m;

c.check();

return c;

}

bigint bigint::operator %(bigint m)

{

return (*this)-((*this)/m)*m;

}

bigint bigint::operator%(int m)

{

if (m<0)

return -((*this)%(-m));

if (m>100000)

return (*this)%bigint(m);

int t=0;

for (int i=length;i>=1;i--)

t=(t*10000+a[i])%m;

return t;

}

bigint sqr(bigint m)

{

return m*m;

}

bigint sqrt(bigint m)

{

if (m.oper<0 || m.length==0)

return 0;

bigint c,last,now,templast;

c.length=(m.length+1)/2;

c.a[c.length]=int(sqrt((double)m.a[c.length*2]*10000+m.a[c.length*2-1])+1e-6);

templast.length=c.length*2;

templast.a[c.length*2-1]=(c.a[c.length]*c.a[c.length])%10000;

templast.a[c.length*2]=(c.a[c.length]*c.a[c.length])/10000;

templast.check();

for (int i=c.length-1;i>=1;i--)

{

last=templast;

int head=0,tail=10000,mid,j,temp;

while (head+1<tail)

{

mid=(head+tail)/2;

now=last;

now.a[2*i-1]+=mid*mid;

for (j=i+1;j<=c.length;j++)

now.a[i+j-1]+=mid*c.a[j]*2;

now.length++;

for (j=2*i-1,temp=0;j<=now.length;j++)

now.a[j]=(temp=(temp/10000+now.a[j]))%10000;

now.check();

if (now<=m)

{

templast=now;

head=mid;

}

else

tail=mid;

}

c.a[i]=head;

}

c.check();

return c;

}

bigint gcd(bigint a,bigint b)

{

return (b==0)?a:gcd(b,a%b);

}

bigint lcm(bigint a,bigint b)

{

return a*b/gcd(a,b);

}

void bigint::operator+=(bigint m)

{

(*this)=(*this)+m;

}

void bigint::operator-=(bigint m)

{

(*this)=(*this)-m;

}

void bigint::operator*=(bigint m)

{

(*this)=(*this)*m;

}

void bigint::operator/=(bigint m)

{

(*this)=(*this)/m;

}

void bigint::operator%=(bigint m)

{

(*this)=(*this)%m;

}

void bigint::operator*=(int m)

{

(*this)=(*this)*m;

}

void bigint::operator/=(int m)

{

(*this)=(*this)/m;

}

void bigint::operator%=(int m)

{

(*this)=(*this)%m;

}

const int maxsize=50+5;

int m,n,L[maxsize],D[maxsize][maxsize];

bigint RA,RB;

bigint F[maxsize];

int main()

{

// freopen("A.in","r",stdin);

freopen("A-small-attempt0.in","r",stdin);freopen("A-small-attempt0.out","w",stdout);

// freopen("A-small-attempt1.in","r",stdin);freopen("A-small-attempt1.out","w",stdout);

// freopen("A-small-attempt2.in","r",stdin);freopen("A-small-attempt2.out","w",stdout);

// freopen("A-large.in","r",stdin);freopen("A-large.out","w",stdout);

int testcase;

scanf("%d",&testcase);

for (int caseId=1;caseId<=testcase;caseId++)

{

printf("Case #%d: ",caseId);

set<int> keys;

scanf("%d%d",&m,&n);

for (int i=0;i<n;i++)

{

scanf("%d",&L[i]);

D[i][0]=1;

for (int j=1;j<L[i];j++)

scanf("%d",&D[i][j]);

sort(D[i],D[i]+L[i]);

for (int j=L[i]-1;j>=0;j--)

D[i][j]-=D[i][0];

}

keys.insert(0);

keys.insert(m);

for (int i=0;i<n;i++)

for (int k=0;k<L[i];k++)

if (D[i][k]>0 && D[i][k]<m)

keys.insert(D[i][k]);

vector<int> lst;

for (set<int>::iterator it=keys.begin();it!=keys.end();++it)

lst.push_back(*it);

RA=0;

RB=1;

for (int i=0;i<n;i++)

{

bigint t_m=m;

RB=RB*t_m;

}

for (int step=0;step+1<SIZE(lst);step++)

{

bigint t_length=lst[step+1]-lst[step];

int key=lst[step];

for (int i=0;i<=n;i++) F[i]=0;

F[0]=1;

for (int i=0;i<n;i++)

{

int cnt=0;

for (int k=0;k<L[i];k++)

if (key-D[i][k]>=0)

cnt++;

for (int k=n;k>=0;k--)

{

bigint t_bad=(m-cnt);

bigint t_good=cnt;

F[k]=F[k]*t_bad;

if (k-1>=0) F[k]=F[k]+F[k-1]*t_good;

}

}

for (int i=1;i<=n;i++)

{

bigint t_h=i*i;

RA=RA+t_length*F[i]*t_h;

}

}

// writeln(RA);

// writeln(RB);

bigint C=RA/RB;

RA=RA-C*RB;

bigint DD=gcd(RA,RB);

RA/=DD;

RB/=DD;

write(C);

printf("+");

write(RA);

printf("/");

writeln(RB);

fflush(stdout);

}

return 0;

}