HDU4043_FXTZ II

题目描述的意思就不说了,自己考虑的时候就是在所有的排列中,碰到大于前面最大的出现数字的时候就乘以一个二分之一,然后求和。

打表后就会发现,答案分子为1*3*5*……*(2*n-1);分母为2*4*6*……*(2*n),这样就很简单了。

直接保存每一个因子出现的次数,然后。。。就可以了。。。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#define M 1000000
#define maxn 1011
using namespace std;

struct node{
    int top,s[1000];
    void init()
    {
        for (int i=0; i<=top; i++) s[i]=0;
        top=0,s[0]=1;
    }
    void mul(int x)
    {
        for (int i=0; i<=top; i++) s[i]*=x;
        for (int i=0; i<top; i++)
            if (s[i]>=M) s[i+1]+=s[i]/M,s[i]%=M;
        while (s[top]>=M) s[top+1]=s[top]/M,s[top]%=M,top++;
    }
    void output()
    {
        printf("%d",s[top]);
        for (int i=top-1; i>=0; i--) printf("%06d",s[i]);
    }
}ans1,ans2;

int a[maxn],pri[maxn],Pnum=0;
bool b[maxn];

void getprim()
{
    for (int i=2; i<maxn; i++)
    {
        if (b[i]) continue;
        pri[++Pnum]=i;
        for (int j=i+i; j<maxn; j+=i) b[j]=true;
    }
}

void add(int x,int v)
{
    for (int i=1; pri[i]<=x; i++)
    {
        while (x%pri[i]==0) x/=pri[i],a[i]+=v;
    }
}

int main()
{
    int T,n;
    getprim();
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        memset(a,0,sizeof a);
        for (int i=1; i<=2*n; i+=2) add(i,1);
        for (int i=2; i<=2*n; i+=2) add(i,-1);
        ans1.init(),ans2.init();
        for (int i=1; i<=Pnum; i++)
        {
            while (a[i]>0) ans1.mul(pri[i]),a[i]--;
            while (a[i]<0) ans2.mul(pri[i]),a[i]++;
        }
        ans1.output();
        printf("/");
        ans2.output();
        printf("\n");
    }
    return 0;
}

 

posted @ 2013-11-22 16:55  092000  阅读(329)  评论(0编辑  收藏  举报