zoukankan      html  css  js  c++  java
  • POJ-3421 X-factor Chains---求因子+递推 或 素因子+组合数学

    题目链接:

    https://vjudge.net/problem/POJ-3421

    题目大意:

    给你一个数X,将X分解成1~X的因子数列,前一个数可以整数后一个数,求满足条件的最大链长以及有多少条这样长的链。

    思路一:

    自己的解答:

    首先求出所有的因子,排序,然后定义一个length数组和tot数组,length[i]表示从第i个因子到最后一个因子的最大链长,tot[i]表示第i个因子到最后一个因子的最大链长的种类,要求length[0]和tot[0]

    已知length[last] = 0,tot[last] = 1(即最后一个因子的链长记为0,这里记为0的话,最后就不用减一,因为题目中第一个因子1不计入链长,数目记为1)

    然后就是从后往前的递推式:可以看个例子:

    n = 100

    下标  0  1  2  3  4  5  6   7  8

    因子  1  2  4  5  10  20   25   50  100

    length  4       3  2  3  2  1  2  1  0

    因子50,100可以整除50,那么length[(50)] = length[(100)] + 1 = 1

    因子25,50可以整除25,那么length[(25)] = length[(50)] + 1 = 2

    同理可求出上述的length数组

    递推式就是length[i] = length[j] + 1(其中下标为j的因子是最小的可以整除下标为i的因子)

    然后就可以推出tot数组

    tot数组就相当于length从后往前有多少个0 1 2 3 4的序列

    n = 100

    下标  0  1  2  3  4  5  6   7  8

    因子  1  2  4  5  10  20   25   50  100

    length  4       3  2  3  2  1  2  1  0

    tot        6       3  1  3  2  1  1  1  1

    1、对于因子50的length=1,因子100的length=0,且100整除50,所以tot[(50)]=tot[(100)]=1 相当于从50开始到最后只有一条路,就是50,100

    2、对于因子25的length=2,因子50的length=1,且50整除25,所以tot[(25)] = tot[(50)] = 1 相当于从25开始到最后只有一条路,就是25,50,100‘

    3、对于因子20的length=1,因子100的length=0,且100整除20,所以tot[(20)] = tot[(100)] = 1 相当于从20开始只有一条路,就是20,100

    4、对于因子10的length=2,因子20和50的length=1,且20和50均整除10,所以tot[(10)]=tot[(50)]+tot[(20)]=2 相当于从10开始有两条路,是10,20,100或者10,50,100

    5、对于因子5的length=3,因子10和25的length=2,且10和25均整除5,所以tot[(5)]=tot[(10)]+tot[(25)]=3 相当于从5开始有三条路,是5,10,20,100或者5,10,50,100或者5,25,50,100

    6、对于因子4的length=2,因子20和50的length=1,且20整除4,50不整除4,所以tot[(4)]=tot[(20)]=1 相当于从4开始有一条路,是4,20,100

    7、对于因子2的length=3,因子4和10和25的length=1,且4和10整除2,25不整除2,所以tot[(2)]=tot[(4)]+tot[(10)]=3 相当于从2开始有三条路,是2,4,20,100或者2,10,20,100或者2,10,50,100

    8、对于因子1的length=4,因子2和5的length=3,且2和5均整除1,所以tot[(1)]=tot[(2)]+tot[(5)]=6 相当于从1开始有六条路,是1,2,10,20,100或者1,2,10,50,100或者1,2,4,20,100或者1,5,10,20,100或者1,5,10,50,100或者1,5,25,50,100


    递推式:tot[i] = sum(tot[j])
    其中第j个因子的length=第i个因子的length-1,并且第j个因子整除第i个因子

     上述递推式文字说明比较繁琐,但是理解之后就特别简单,抓紧题目的意思,后一个因子整除前一个因子,然后递推式就可以想出来了。

     1 #include<iostream>
     2 #include<vector>
     3 #include<queue>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdio>
     7 #include<set>
     8 #include<map>
     9 #include<cmath>
    10 using namespace std;
    11 typedef pair<int, int> Pair;
    12 typedef long long ll;
    13 const int INF = 0x3f3f3f3f;
    14 int T, n, m;
    15 int length[1005], tot[1005];
    16 vector<int> divisor(int n)
    17 {
    18     vector<int>res;
    19     for(int i = 1; i * i <= n; i++)
    20     {
    21         if(n % i == 0)
    22         {
    23             res.push_back(i);
    24             if(i != n / i)res.push_back(n / i);
    25         }
    26     }
    27     return res;
    28 }
    29 int main()
    30 {
    31     while(cin >> n)
    32     {
    33         vector<int>a = divisor(n);
    34         sort(a.begin(), a.end());
    35         memset(length, 0, sizeof(length));
    36         memset(tot, 0, sizeof(tot));
    37         int m = a.size();
    38         length[m - 1] = 0;
    39         for(int i = m - 2; i >= 0; i--)
    40         {
    41             for(int j = i + 1; j < a.size(); j++)
    42             {
    43                 if(a[j] % a[i] == 0)
    44                 {
    45                     length[i] = length[j] + 1;
    46                     break;
    47                 }
    48             }
    49         }
    50         tot[m - 1] = 1;
    51         for(int i = m - 2; i >= 0; i--)
    52         {
    53             for(int j = i + 1; j < m; j++)
    54             {
    55                 if(length[j] + 1 == length[i])
    56                 {
    57                     if(a[j] % a[i] == 0)
    58                         tot[i] += tot[j];
    59                 }
    60             }
    61         }/*
    62         for(int i = 0; i < m; i++)
    63         {
    64             cout<<a[i]<<" "<<length[i]<<" "<<tot[i]<<endl;
    65         }*/
    66         cout<<length[0]<<" "<<tot[0]<<endl;
    67     }
    68 }

    思路二:

    网上常规方法,直接求出所有素因子,然后素因子的数目就是链长,不难理解,每次递增的时候,前一个因子乘上一个素因子,直到所有素因子乘完,就到达n了

    具体的数目就是这些素因子的排列组合的数目,比如100=2*2*5*5,素因子4个,排列组合次数为4!/(2!*2!) = 6,就是简单的组合数学 

     代码随便在网上找就行了,这里就不赘述了

  • 相关阅读:
    什么是 go vendor
    Golang包管理工具之govendor的使用
    国内的go get问题的解决
    集群、限流、缓存 BAT 大厂无非也就是这么做
    Gin框架中文文档
    GO——beego简单开发实例(二)
    C++11 并发指南四(<future> 详解一 std::promise 介绍)(转)
    C++11 并发指南三(std::mutex 详解)(转)
    C++11 并发指南二(std::thread 详解)(转)
    用C++设计一个不能被继承的类(转)
  • 原文地址:https://www.cnblogs.com/fzl194/p/8811089.html
Copyright © 2011-2022 走看看