【(阶乘的质因数分解)算组合数】【TOJ4111】【Binomial efficient】

原创 2015年07月08日 18:40:15

n<=10^6

m<=10^6

p=2^32


用unsigned int 可以避免取模


我写的SB超时 阶乘分解代码

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
using namespace std;
const unsigned int N=1000000+5;
unsigned int tag[N],p[N],z[N],mm[N];
unsigned int cnt = 0;
unsigned int n,m;
unsigned int quickpow(unsigned int m,unsigned int n)
{
    unsigned int b = 1;
    while (n > 0)
    {
          if (n & 1)
             b = (b*m);
          n = n >> 1 ;
          m = (m*m);
    }
    return b;
}

void get_prime()
{
    tag[1]=1;
    tag[0]=1;
    for (unsigned int i = 2; i < N; i++)
    {
        if (!tag[i])    p[cnt++] = i;
        for (unsigned int j = 0; j < cnt && p[j] * i < N; j++)
        {
            tag[i*p[j]] = 1;
            if (i % p[j] == 0)
                break;
        }
    }
}
unsigned int FIND(unsigned int x)
{
    unsigned int l=0,r=cnt-1;
    while(l<=r)
    {
        unsigned int m=(l+r)/2;
        if(p[m]==x) return m;
        else if(p[m]<x) l=m+1;
        else r=m-1;
    }
}
void fenjie(unsigned int *a,unsigned int d)
{
    for(unsigned int i=0;i<cnt&&p[i]<=sqrt(d);i++)
    {
        while(d%p[i]==0)
        {
            d=d/p[i];
            a[i]++;
        }
    }
    if(tag[d]==0)
    {
        unsigned int t=FIND(d);
        a[t]++;
    }
}
int main()
{
   // freopen("a.in","r",stdin);
    get_prime();
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        memset(z,0,sizeof(z));
        memset(mm,0,sizeof(mm));
        for(unsigned int i=n;i>=n-m+1;i--)
            fenjie(z,i);
        for(unsigned int i=1;i<=m;i++)
            fenjie(mm,i);
        unsigned int ans=1;
        for(unsigned int i=0;i<cnt;i++)
            {
                z[i]=z[i]-mm[i];
                ans=ans*quickpow(p[i],z[i]);
            }
        printf("%u\n",ans);
    }
}

利用阶乘的质因数分解!


比如250!


1*2*3*4*5*6*7*8*9*10*11*12*13*14.....250

中3的质因子个数 除了3后变成(不是倍数的不管)计算3^1次方的为250/3个

又变成 1 2 3 .....250除3  

重复上面 知道 3^2 为250/(3^2) 


所以阶乘的质因数分解是另外的简单算法

void getcn(int n)
{
	int ans = 0;
	int i;
	for (i = 1; i <= prime[0] && prime[i] <= n; i++)
	{
		int tmp = n;
		while (tmp)
		{
			num[i] += tmp / prime[i];
			tmp /= prime[i];
		}
	}
	num[0] = i;
}

所以最后的代码是

#include <string.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <algorithm>
#include <vector>
#include <string.h>
#include <time.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#define INF 0x3f3f3f3f
#define MAXN 1000005
#define Precision 100005
#define MAX_INT 2147483647
#define Pi acos(-1.0)
#define lowbit(x) ((x)&(-x))
#define Lson root<<1,left,mid
#define Rson root<<1|1,mid+1,right
#define LL long long
#define ULL unsigned long long
#define fresh(x) memset(x,0,sizeof(x))
using namespace std;


int prime[MAXN];
int num[MAXN];


void print()
{
<span style="white-space:pre">	</span>memset(prime, 0, sizeof(prime));
<span style="white-space:pre">	</span>for (int i = 2; i <= 1000000; i++)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (!prime[i]) prime[++prime[0]] = i;
<span style="white-space:pre">		</span>for (int j = 1; j <= prime[0] && prime[j] <= 1000000 / i; j++)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>prime[prime[j]*i] = 1;
<span style="white-space:pre">			</span>if (i % prime[j] == 0) break;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
}


unsigned qpow(unsigned a, unsigned b)
{
<span style="white-space:pre">	</span>unsigned ans = 1;
<span style="white-space:pre">	</span>while (b)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (b & 1)
<span style="white-space:pre">			</span>ans *= a;
<span style="white-space:pre">		</span>b >>= 1;
<span style="white-space:pre">		</span>a *= a;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return ans;
}


void getcn(int n)
{
<span style="white-space:pre">	</span>int ans = 0;
<span style="white-space:pre">	</span>int i;
<span style="white-space:pre">	</span>for (i = 1; i <= prime[0] && prime[i] <= n; i++)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>int tmp = n;
<span style="white-space:pre">		</span>while (tmp)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>num[i] += tmp / prime[i];
<span style="white-space:pre">			</span>tmp /= prime[i];
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>num[0] = i;
}


void getcm(int m)
{
<span style="white-space:pre">	</span>int ans = 0;
<span style="white-space:pre">	</span>int i;
<span style="white-space:pre">	</span>for (i = 1; i <= prime[0] && prime[i] <= m; i++)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>int tmp = m;
<span style="white-space:pre">		</span>while (tmp)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>num[i] -= tmp / prime[i];
<span style="white-space:pre">			</span>tmp /= prime[i];
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
}


int main()
{
<span style="white-space:pre">	</span>int n, m, T;
<span style="white-space:pre">	</span>print();
<span style="white-space:pre">	</span>//printf("%d\n", prime[prime[0]]);
<span style="white-space:pre">	</span>//cout << prime[0];
<span style="white-space:pre">	</span>scanf("%d", &T);
<span style="white-space:pre">	</span>while (T--)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>memset(num, 0, sizeof(num));
<span style="white-space:pre">		</span>scanf("%d%d", &n, &m);
<span style="white-space:pre">		</span>getcn(n);
<span style="white-space:pre">		</span>getcm(m);
<span style="white-space:pre">		</span>getcm(n - m);
<span style="white-space:pre">		</span>unsigned ans = 1;
<span style="white-space:pre">		</span>for (int i = 1; i <= num[0]; i++)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>ans *= qpow(prime[i], num[i]);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>printf("%u\n", ans);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

阶乘质因数分解

http://acm.nyist.net/JudgeOnline/problem.php?pid=70 阶乘因式分解(二) 时间限制:3000 ms  |  内存限制:65535 KB 难度...

FZU 1851 组合数 (分解质因数)

题意:输出组合数C(n,m)的质因数 思路:将分母,分子分别质因数分解(短除法),记录每个质因数个数,用分母各个质因数的个数-分子的质因数的个数,即可; #include #include #...

N!含有质因子2的个数

题目来源于《编程之美》上的一道题。

阶乘因式分解:求阶乘后某因子个数

给定两个数m,n 求m!分解质因数后因子n的个数。 这道题涉及到了大数问题,如果相乘直接求的话会超出数据类型的范围。 下面给出一种效率比较高的算法,我们一步一步来。 m!=1*2*3*……*(...

[codevs2959]阶乘质因数分解

n!(n≤10000)是一个很大的数,对n!进行质因数分解后形式为:2p1*3p2*…kpk,其中k为某个质数,pi为对应质数的方幂。输入描述 Input Description 一个正整数n输出描...

1008 N的阶乘 mod P

1008 N的阶乘 mod P 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 输入N和P(P为质数)...
  • Cai_Nia
  • Cai_Nia
  • 2016年09月23日 22:11
  • 732

将n(0<=n<=10000)的阶乘分解质因数,求其中有多少个m

给定两个数m,n,其中m是一个素数。 将n(0 输入 第一行是一个整数s(0 随后的s行, 每行有两个整数n,m。 输出 输出m的个数。 样例输入 2 100 5 16...

阶乘质因子分解(唯一分解定理)

阶乘质因子分解题目描述: 对N!进行质因子分解。 输入输出格式: 输入格式: 输入数据仅有一行包含一个正整数N,N...
  • cax1165
  • cax1165
  • 2016年09月11日 08:35
  • 441

联合权值 【图论】【数学优化】Codevs3728

两个问题都需要通过每个节点的相邻点的思维方式来解 第一问 每个节点的子节点之间彼此组成联合点 如图↓ 1和3, 1和4互为联合点第二问(晚上再写) PS:联合权值的和,(1,3)和(3,1)不算重...

FZU 2082 求树上任意点间距离 边权转为点权 树链剖分

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2082 思路: 边权转点权: 由于线段树中的点是节点,则把题目给的边权值作为 边一端 距离根更远的节点的点权值。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【(阶乘的质因数分解)算组合数】【TOJ4111】【Binomial efficient】
举报原因:
原因补充:

(最多只允许输入30个字)