zoukankan      html  css  js  c++  java
  • bzoj 1005: [HNOI2008]明明的烦恼 树的prufer序列+万进制

    题目传送门

    思路:

      这道题需要前置知识prufer编码,这篇博客对prufer编码和这道题的分析写的很好。

      这里主要讲一些对大数阶乘的分解,一个办法当然是用高精度,上面这篇博客用的是java,还有一个办法是用万进制,但是普通的万进制只能计算乘法,而这里需要用到除法,又不能用逆元(因为没有取模)怎么办呢?

      我们发现,上面那篇博客得到的式子是一个组合数的式子,所以必然是整数,如果把分子和分母共同进行质因子分解,那么上面的质因子的数量必然大于下面的,所以我们就把每一个阶乘和数字进行质因子分解,然后对分解出来的质因子用万进制处理(我实际上用的是百万进制)。

      代码debug的时候有个很小的地方错了,看了一遍hzwer聚聚的代码,,然后就变默写了。。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    #define fpn() freopen("simple.in","r",stdin)
    #define rd read()
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,t=1;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    const int maxn=1010;
    int p=1000000;
    int ans[maxn],num[maxn],pri[maxn],cnt,l,tot;
    int d[maxn],n,sum;
    inline bool judge(int x){
        for(int i=2;i<=sqrt(x);i++){
            if(x%i==0)return false;
        }
        return true;
    }
    void prim(){
        for(int i=2;i<=1000;i++)
        {
            if(judge(i))pri[++cnt]=i;
        }
    }
    void resolve(int x,int w){
        for(int k=2;k<=x;k++)
        {
            int a=k;
            for(int i=1;i<=cnt;i++){
                if(a<=1)break;
                while(a%pri[i]==0){
                    num[i]+=w;
                    a/=pri[i];
                }
            }
        }
    }
    void mul(int x){
        for(int i=1;i<=l;i++)ans[i]*=x;
        for(int i=1;i<=l;i++){
            ans[i+1]+=ans[i]/p;
            ans[i]%=p;
        }
        while(ans[l+1]>0){
            l++;
            ans[l+1]+=ans[l]/p,ans[l]%=p;
        }
    }
    void print()
    {
        for(int i=l;i>0;i--)
            if(i==l)printf("%d",ans[i]);
            else printf("%06d",ans[i]);
    }
    int main(){
        prim();
        cin>>n;
        if(n==1){
            int x;
            cin>>x;
            if(!x)printf("1
    ");
            else puts("0");
            return 0;
        }
        int flag=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&d[i]);
            if(d[i]!=-1){
                if(d[i]==0)flag=1;
                tot++;
                sum+=d[i]-1;
            }
        }
        if(sum>n-2||flag){
            puts("0");
            return 0;
        }
        resolve(n-2,1);
        resolve(n-2-sum,-1);
        for(int i=1;i<=n;i++){
            if(d[i]!=-1){
                resolve(d[i]-1,-1);
            }
        }
        ans[++l]=1;
        for(int i=1;i<=cnt;i++){
            while(num[i]--){
                mul(pri[i]);
            }
        }
        for(int i=1;i<=n-2-sum;i++){
            mul(n-tot);
        }
        print();
        return 0;
    }
    View Code
  • 相关阅读:
    一文总结十大经典排序算法(思维导图 + 动图演示 + 代码实现 C/C++/Python + 致命吐槽)
    VulnHub——Kioptrix Level 2
    史上最全Redis面试题(2020最新版)
    js 根据秒数获取多少小时,多少分钟,多少秒
    RabbitMQ的死信队列
    女朋友也能看懂的多线程同步
    RabbitMQ的备份交换器
    BI Publisher(rtf)模板开发语法大全
    修改CUSTOM.PLL文件调用客户化FORM&修改标准FORM
    EBS客户化迁移SQL
  • 原文地址:https://www.cnblogs.com/mountaink/p/10433211.html
Copyright © 2011-2022 走看看