zoukankan      html  css  js  c++  java
  • Counting Factor Trees [ZOJ 3405]

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4013

    记忆化搜索,学到啦用map做映射不用担心数组开多大的问题,还有map<vector<int>,int>vis;

    可以对一个list进行映射,由于10^9以内的素数因子的组合很少,可以记忆化。

    View Code
    //记忆化搜索,学到啦用map做映射不用担心数组开多大的问题,还有map<vector<int>,int>vis;
    
    //可以对一个list进行映射,由于10^9以内的素数因子的组合很少,可以记忆化。
    const int MM = 11111;
    typedef long long int64;
    int N;
    int prm[MM], cnt;
    bool isp[MM];
    
    int get_prime(int n) {
        int i,j,k=0;
        int s, e=(int)(sqrt(0.0+n)+1);
        for(i=0;i<=n;i++) isp[i]=true;
        prm[k++]=2; isp[0]=isp[1]=false;
        for(i=4;i<n;i+=2) isp[i]=false;
        for(i=3;i<e;i+=2) if(isp[i]) {
            prm[k++]=i;
            for(s=(i<<1), j=i*i; j<n ; j+=s) isp[j]=false;
        }
        for(; i<n ; i+=2) if(isp[i]) prm[k++]=i;
        return k; 
    }
    
    //1000000000
    map<vector<int>,int64>vis;
    map<int,int64>dp;
    
    int64 dfs(int x) {
        if(x<MM && isp[x]) return 1;
        if(dp[x]) return dp[x];
        vector<int>a; int m=x,j;
        for(j=0;j<cnt && prm[j]*prm[j]<=m;j++) {
            if(m%prm[j]==0) {
                int cc=0;
                while(m%prm[j]==0) cc++,m/=prm[j];
                a.push_back(cc);
            }
        }
        if(m>1) a.push_back(1);
        sort(a.begin(),a.end());
        if(vis[a]) return vis[a];
        int64 res=0,tmp;
        int tt=(int)sqrt(x*1.0)+1;
        bool ff=false;
        for(int i=2;i<tt;i++) if(x%i==0) {
            ff=true;
            tmp=dfs(x/i)*dfs(i);
            if((i*i)!=x) tmp<<=1;
            res+=tmp;
        }
        if(!ff) res=1;
        if(!dp[x]) dp[x]=res;
        vis[a]=res;
        return res;
    }
    void solve() {
        int i,j,k,tt;
        int64 ans=0,tmp;
        if(dp[N]) {printf("%lld\n",dp[N]);}
        else {
            ans=dfs(N);
            printf("%lld\n",ans);
        }
    }
    
    int main() {
        cnt=get_prime(MM); vis.clear(); dp.clear();
        while(scanf("%d",&N)!=EOF) solve();
        return 0;
    }

     对N进行因式分解有N=p1^r1p2^r2.......pn^rn; 记sum=r1+r2+..+rn,则sum个节点能组成h(sum)(Catlan数)个二叉树。

    N=p1^r1p2^r2.......pn^rn的排列组合*h(sum)=ans。

    View Code
    const int MM = 55555;
    const int maxn = 80;
    typedef long long int64;
    //typedef __int64 int64;
    //#define debug puts("wrong")
    int N;
    int prm[MM], cnt;
    int64 com[maxn][maxn];
    bool isp[MM];
    
    void get_com() {
        int i,j,k;
        for(i=0;i<maxn;i++) {
            com[i][0]=1;
            for(j=1;j<=i;j++) com[i][j]=com[i-1][j-1]+com[i-1][j];
        }
    }
    
    int get_prime(int n) {
        int i,j,k=0;
        int s, e=(int64)(sqrt(0.0+n)+1);
        for(i=0;i<=n;i++) isp[i]=true;
        prm[k++]=2; isp[0]=isp[1]=false;
        for(i=4;i<n;i+=2) isp[i]=false;
        for(i=3;i<e;i+=2) if(isp[i]) {
            prm[k++]=i;
            for(s=(i<<1), j=i*i; j<n ; j+=s) isp[j]=false;
        }
        for(; i<n ; i+=2) if(isp[i]) prm[k++]=i;
        return k; 
    }
    
    void solve() {
        int i,j,k,tmp=N,sum=0;
        int64 ans=1;
        for(i=0;i<cnt && prm[i]*prm[i]<=N;i++) {
            if(tmp%prm[i]==0) {
                int cc=0;
                while(tmp%prm[i]==0) cc++,tmp/=prm[i];
                sum+=cc;
                ans*=com[sum][cc];
            }
        }
        if(tmp>1) sum++,ans*=sum;
        sum--;
        ans*=com[sum<<1][sum]/(sum+1);
        printf("%lld\n",ans);
    }
    
    int main() {
        cnt=get_prime(MM); get_com();
        while(scanf("%d",&N)!=EOF) solve();
        return 0;
    }
  • 相关阅读:
    miniui mini-combobox的使用
    xsd文件记录
    Hibernate 一次查询分多次返回 避免内存溢出
    卡口扩展信息
    删除 maven仓库,更新失败的jar包命令
    杀windows进程
    layer 遮罩层等待
    math() 对象
    JavaScript 字符串方法
    JavaScript 数组遍历方法;
  • 原文地址:https://www.cnblogs.com/zhang1107/p/3050393.html
Copyright © 2011-2022 走看看