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,就是简单的组合数学 

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

  • 相关阅读:
    1026 Table Tennis (30)
    1029 Median
    1025 PAT Ranking (25)
    1017 Queueing at Bank (25)
    1014 Waiting in Line (30)
    1057 Stack (30)
    1010 Radix (25)
    1008 Elevator (20)
    字母大小写转换
    Nmap的基础知识
  • 原文地址:https://www.cnblogs.com/fzl194/p/8811089.html
Copyright © 2011-2022 走看看