PKU : 3421 - X-factor Chains
問題概要
http://poj.org/problem?id=3421
Xが入力として与えられ, 次のようなm+1個の数を含む数列を考えます.
- 1 = X0, X1, X2, …, Xm = X
Xi番目の項は, X_(i-1)番目の項で割り切ることができ, Xi > X_(i-1)が成り立っています.
このとき, この数列の最大長と, 最大長となる数列が何種類存在するかを答えてください.
アルゴリズム
結論だけいうと
- 数列の最大長は「Xの素因数の数」
- 種類数は「素因数の順列の数」
最後の項は, Xにしなければいけないから, X0〜X_(m-1)の項は, 必ずXの素因数を掛け合わせた数になります. そのため, どうがんばっても, 最大長はXの素因数の数にしかならないです.
初項から, 順番に数列を求めていくとき, 素因数のかける順番を変えれば, 違う数列となるので, 種類数は素因数の順列の数となります.
プログラム
頭悪い方法でやってるかもです.
//階乗計算 ll fact(int x){ ll res = 1; REP(i,2,x+1){ res *= i; } return res; } int main(){ int n; while(cin>>n){ vector<int> f; //Nを割り切る素数が, それぞれ何回出現したか int sum = 0; //Nの素因数の数 //素因数計算 for(int now = 2; now*now <= n; now++){ if(n % now != 0) continue; int c = 0; while(n % now == 0){ n /= now; c++; } f.push_back(c); sum += c; } if(n != 1){ f.push_back(1); sum++; } //順列数計算と, 重複をはぶく計算 ll cal = fact(sum); rep(i,f.size()){ cal /= fact(f[i]); } cout<<sum<<" "<<cal<<endl; } }