poj3421(多重集排列,唯一分解定理)

来源:互联网 发布:怎么恢复数据 编辑:程序博客网 时间:2024/05/21 15:03
/*translation:给出一个数,求能够形成的x数链最长是多少?(x数链是指以1开始,以n结尾,其中任意相邻的两个数,前面的数都能整除后面)solution:多重集排列计数,唯一分解定理由x数链的性质可以发现,将n分解为其质因数相乘的形式后,数链中任何一个数必定是这些质因数的某个组合,且任意相邻的2个质因数中后面的数必定是在前面的数的质因数的组合的基础上再乘上另外的一个质因数。所以很容易发现,数链的长度就是其质因数的次数的总和,然后将质因数泛化成物品,质因数的次数为每类物品的数量,则最后的答案就是求这些物品的多重集总排列。套用公式即可!note:* 多重集合总排列公式:  设第i类物品数量为ni。另n=n1+n2+n3+...+ni  则总排列数量:n! / (n1! + n2! + n3! + ... + ni!)* 关于多重集排列可以参考该文档:http://www.docin.com/p-156949243.htmldate:2016.6.27*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1000 + 5;typedef long long ll;ll n, id, cnt;ll factor[maxn][2];//0存底数,1存指数void get_fac(ll n){for(ll i = 2; i*i <= n; i++){if(n % i)continue;factor[++id][0] = i;factor[id][1] = 0;while(n % i == 0){factor[id][1]++;n /= i;}}if(n != 1){factor[++id][0] = n;factor[id][1] = 1;}}ll computes(ll x){ll res = 1;for(ll i = x; i >= 1; i--)res *= i;return res;}int main(){    while(cin >> n){id = 0;get_fac(n);ll res = 0;for(int i = 1; (ll)i <= id; i++)res += factor[i][1];cnt = computes(res);//计算res!for(int i = 1; (ll)i <= id; i++)cnt /= computes(factor[i][1]);cout << res << " " << cnt << endl;}    return 0;}

0 0
原创粉丝点击