【BZOJ 1005】[HNOI2008]明明的烦恼(化简的另一种方法)

【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1005

【题意】

【题解】

题目和题解在上一篇;
这里 对
【(m^(n-2-tot))* (n-2)!】/【(n-2-tot)!* (d[1]-1)!*(d[2]-1)!……(d[n]-1)!】;
这个式子的化简再说一个方法;
对于n!
最后分解成质因子的时候;
质因子p的指数应该为
∑(n/i);
这里i为p,p^2,p^3….p^x,且p^x<=n
这样;
因为最大要求的阶乘为(n-2)!
所以先处理出2..n-2之间哪些数是质数;
然后对于x!
直接枚举2..x之间的那些质数;
然后i=p,p平方,p立方,p的4次方..那样加上n/i;
知道某个质数的指数之后,直接根据是分子还是分母,分别加上或减去那个∑(n/i)就好;
这样就不用1..x里面每个数都再去分解一次质因数了;

//直接暴力搞
    for (int i = 1;i <= x;i++)
    {
        int x = i;
        for (int j= 2;j*j <= x;j++)
        while (x%j==0)
        {
            cnt[j]->change;
            x/=j;
        }
    }
//更优雅的方法
    for (int i = 2;i <= x;i++)
    {
        if (zhishu[i])
        {
            zhi=0
            for (int j = i;j <= x;;j*=i)
                zhi+=x/j;
            cnt[i]->change(zhi);
        }
    }


【完整代码】

/**************************************************************
    Problem: 1005
    User: chengchunyang
    Language: C++
    Result: Accepted
    Time:36 ms
    Memory:1316 kb
****************************************************************/

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1100;

int n,d[N],m,tot,cnt[N];
int ans[N],len = 1;
bool bo[N];

void go(int t,int x)
{
    rep1(i,2,t)
        if (bo[i])
        {
            int num = 0;
            for (int j = i;j <= t;j*=i)
                num+=t/j;
            cnt[i]+=x*num;
        }
}

void cheng(int p)
{
    int x = 0;
    rep1(i,1,len)
    {
        ans[i] = ans[i]*p+x;
        x = ans[i]/10;
        ans[i]%=10;
    }
    while (x>0)
    {
        ans[++len] = x;
        x = ans[len]/10;
        ans[len]%=10;
    }
}

bool is(int x)
{
    rep1(i,2,int(sqrt(x)))
        if (x%i==0)
            return false;
    return true;
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    rei(n);
    rep1(i,1,n)
    {
        rei(d[i]);
        if (d[i]==0) return puts("0"),0;
        if (d[i]==-1)
            m++;
        else
            d[i]--,tot+=d[i];
    }
    if (n-2<tot)
        return puts("0"),0;
    memset(bo,false,sizeof bo);
    rep1(i,2,n-2)
        if (is(i)) bo[i] = true;
    go(n-2,1);
    go(n-2-tot,-1);
    rep1(i,1,n)
        go(d[i],-1);
    ans[1] = 1;
    rep1(i,2,n)
        rep1(j,1,cnt[i])
            cheng(i);
    rep1(i,1,n-2-tot)
        cheng(m);
    rep2(i,len,1)
        printf("%d",ans[i]);
    return 0;
}

posted @ 2017-10-04 18:45  AWCXV  阅读(137)  评论(0编辑  收藏  举报