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; }