poj 3378 Crazy Thairs

http://poj.org/problem?id=3378

要想求以第k个数为5个数中最后一个数的组合数量

就要求从1到k-1这些数中比第k个小且是4个数中最后一个数的这些组合数量 之和

依次类推

求和用树状数组来维护  最后结果可能超long long 我用了大整数

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<map>

#include<vector>

#include<stack>

#include<set>

#include<map>

#include<queue>

#include<algorithm>

#include<cmath>

#define LL long long

//#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

const int INF=0x3f3f3f3f;

const int N=50005;

const int K=25;

struct node

{

    int a,k,I;

}mem[N];

struct bigInt

{

    int a[K],L;

    const bigInt operator +(bigInt x) const

    {

        bigInt y;

        y.L=L;

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

        y.a[i]=a[i];

        for(int i=L;i<K;++i)

        y.a[i]=0;

        int m=max(y.L,x.L);

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

        {

            y.a[i]+=x.a[i];

            if(y.a[i]>=10)

            {y.a[i+1]+=1;y.a[i]-=10;}

        }

        if(y.a[m]!=0)

        ++m;

        y.L=m;

        return y;

    }

};

bigInt c[6][N],bigZero,bigOne;

int lowbit(int x)

{

    return x&(-x);

}

void add(int k,int x,bigInt w,int m)

{

    while(x<=m)

    {

        c[k][x]=c[k][x]+w;

        x+=lowbit(x);

    }

}

bigInt sum(int k,int x)

{

    bigInt tmp=bigZero;

    while(x>0)

    {

        tmp=tmp+c[k][x];

        x-=lowbit(x);

    }

    return tmp;

}

bool cmp(node x,node y)

{

    return x.a<y.a;

}

bool cmp1(node x,node y)

{

    return x.I<y.I;

}

int main()

{

    bigZero.L=1;

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

    bigZero.a[i]=0;

    bigOne=bigZero;

    bigOne.a[0]=1;

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

    int n;

    while(scanf("%d",&n)!=EOF)

    {

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

        for(int j=0;j<N;++j)

        c[i][j]=bigZero;

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

        {

            scanf("%d",&mem[i].a);

            mem[i].I=i;

        }

        sort(mem,mem+n,cmp);

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

        {

            if(i==0)

            {mem[i].k=1;continue;}

            if(mem[i].a==mem[i-1].a)

            mem[i].k=mem[i-1].k;

            else

            mem[i].k=mem[i-1].k+1;

        }

        int m=mem[n-1].k;

        sort(mem,mem+n,cmp1);

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

        {

            add(1,mem[j].k,bigOne,m);

            for(int i=2;i<=5;++i)

            {

               add(i,mem[j].k,sum(i-1,mem[j].k-1),m);

            }

        }

        bigInt ans=sum(5,m);

        for(int i=ans.L-1;i>0;--i)

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

        printf("%d\n",ans.a[0]);

    }

    return 0;

}

  

你可能感兴趣的:(AIR)