poj 3421

题目给出一个X,求从1到X列出一串数字X0,X1,X2..Xm使得 X0=1,Xm=X,Xi < Xi+1 且Xi+1%Xi=0的m的最大值及方法数
此题本质是让你求X的素数因子,然后进行组合。
比如我们有个100, 100=2^2 * 5^2,那么m的最大值为2+2=4,方法数为4!/(2!+2!)
我们可以这样将100的素数因子排列, 2 2 5 5,那么从前往后乘,得到1 2 4 20 100,这就是一种方法,我们也可以这样排
2 5 2 5,那么得到的就是1 2 10 20 100,可以看出m的最大值就是素因子指数之和,方法数就是将所有素数因子指数的全排列,我们知道,如果有num1个A,num2个B,num3个C。。。将A,B,C进行全排列的排列数为 (num1+num2+num3)! / (num1!*num2!*num3!)

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
#include<set>
#include<bitset>
//#define ONLINE_JUDGE
#define eps 1e-5
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,num) scanf("%d%d%d",&a,&b,&num)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define ll long long
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
//#pragma comment(linker,"/STACK:1024000000,1024000000")
int n,m,c;
#define N 210
#define M 1050100
#define Mod 1000000000
#define p(x,y) make_pair(x,y)
const int MAX_len=550;
int f[M];
int prime[M];
int tot;
ll fab[25];
void get_Prime(){                           //素数打表
    memset(f,0,sizeof f);
    tot=0;
    int p = (int)sqrt(M)+1;
    f[1] = 1;
    for(int i=2;i<p;i++){
        if(f[i]) continue;
        prime[tot++] = i;
        for(int j=i;i*j<M;j++)
            f[i*j] = 1;
    }
    fab[0]=1;
    for(ll i=1;i<25;i++){
        fab[i] = fab[i-1]*i;
    }
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
#endif
    get_Prime();
    while(sf(n)!=EOF){
        int tmp = n;
        int sum1=0;
        ll sum2=1;
        for(int i=0;i<tot&&prime[i]<=tmp;i++){
            if(tmp%prime[i] == 0){
                int cnt=0;
                while(tmp%prime[i] == 0){
                    tmp /= prime[i];
                    cnt++;
                }
                sum1 += cnt;  //计算指数之和
                sum2 *= fab[cnt];   //计算指数阶乘的和
            }
            if(!f[tmp]){
                sum1++;
                break;
            }
        }
        printf("%d %I64d\n",sum1,fab[sum1]/sum2);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值