快速求出n!的质因数的个数

一般做组合数的题目都要进行质因数的分解,我们一般是for循环对每个数进行质因数分解,大多数情况都不会超时,但极少数的情况下,题目会不允许这样的做法,所以我们需要学会一种更快的方法来求质因数。

我们一般的方法是对每个数进行质因数分解:

inline void calc(int x,int val)
{
    int xx=x;
    for(int i=2;i*i<=xx;i++)
    {
        while(x%i==0)//不断进行除法,找出多少的当前的质数
        {
            c[i]+=val;x/=i;
        }
        if(x==1)break;
    }
    if(x>1)c[x]+=val;//如果剩下的数也是个质数,那么这个质数也要加上val
}

但如果想要更快的分解,我们可以直接对n!进行分解:

首先先进行素数筛选,得出素数表

然后进行如下操作:

1 inline long long calc(int n,int x)//n表示要求的n!,x表示想要求的质数,函数的作用是求出x的个数
2 {   long long cnt=0;
3     for(long long i=x;i<=n;i*=x)//为了防止i的溢出,所以我们要开long long
4       {cnt+=n/i;
5             }
6     return cnt;
7     }   

我们来一个样例说明一下:

1  2  3  4  5  6  7  8         我们求得在8!中2的个数

1      1      1      1         首先我们先计算出2的倍数的个数:8/2=4

            1              1         其次我们计算出4的倍数的个数:    8/4=2(上面一个式子求出了第一层,现在求第二层)

                            1         最后我们解出第三层的2的个数:    8/8=1

我们把4+2+1=7,所以一共7个2出现了。

 即:cnt(x)=[n/(x^1)]+[n/(x^2)]+[n/(x^3)]+...(直到x的次方大于n)

到这里我们可以发现:我们平时求的方法是一列一列求的(就是每一个数算一遍),而这个方法我们每一行每一行的求,虽然效果一样,但求起来速度很快。值得学习。

故做法:

  1.先把素数表打好

  2.for循环把小于n的每个质数进行一次运算,用数组记录

  3.结束

非常快。

时间: 2024-09-28 18:00:47

快速求出n!的质因数的个数的相关文章

快速求出n!质因数的个数

一般做组合数的题目都要进行质因数的分解,我们一般是for循环对每个数进行质因数分解,大多数情况都不会超时,但极少数的情况下,题目会不允许这样的做法,所以我们需要学会一种更快的方法来求质因数. 我们一般的方法是对每个数进行质因数分解: 1 inline void calc(int x) 2 { 3 int xx=x; 4 for(int i=2;i*i<=xx;i++) 5 { 6 while(x%i==0)//不断进行除法,找出多少的当前的质数 7 { 8 c[i]++;x/=i; 9 } 10

求出整数中1的个数

输入一个整数,求出它的二进制1的个数.考虑的知识点:负数怎么求,因为计算机中存放都是补码的形式存储一个数.因为正数的源码,反码,补码都是一样,不用考虑.但是负数就要考虑了,比如-0,它的源码应该是10000000 00000000 00000000 000000000 00000000,所以负数要考虑. 下面是代码实现: #ifndef _FINDNUMBEROF1_ #define _FINDNUMBEROF1_ /*================================ Macro

快速求两个数组交集算法

快速求出两个数组的交集的算法,如果用循环遍历的方法,其时间复杂度为O(N^N),在面试中一般不考虑这种方法. 这里提供一种快速算法,算法实现步骤如下: 1. 找到arr1的最大数max,创建一个max+1大小的数组result. 2. 以arr1中的值作为result的下标,该索引处的值+1. 3. 在result数组中遍历arr2中的值为下标处的值,如果该索引值不为0,则代表该值是两者的交集,保留. 程序实现如下: /** * 求两个数组的交集 * @param arr1 * @param a

求 质因数的个数

如何 快速求一个数的质因数的个数 for(int i = 1; i <= 1000000; i++) cnt[i] = 2; cnt[1] = 1; for(int i = 2; i <= 1000000; i++){ for(int j = i+i; j <= 1000000; j += i) cnt[j]++; } 原文地址:https://www.cnblogs.com/ccut-ry/p/8409965.html

欧拉计划013(ProjectEuler013):求出10个数乘积最大的

申明:之前的所有欧拉计划都是用python来写的,的确python来写,代码量极少,学习起来也很方便.但是最近为了找java工作,所以用Java来完成欧拉计划的题,来复习一下Java. Large sum Problem 13 Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. 371072875339021027987979982208375902465101357402

编程题:已知一个一维数组a[10]中有10个数,求出第m个数到第n个数的和。其中m、n由键盘输入。

#include<stdio.h> int sum(int *q,int n) { int i,s=0; for(i=0;i<n;i++,q++) s+=*q; return s; } void main() { int n,m,a[10]={1,2,3,4,5,6,7,8,9,10}; int *p; printf("Please input m and n(m<n<10):\n"); scanf("%d,%d",&m,&am

编写一个程序,用户输入两个数,求出其加减乘除,并用消息框显示计算结果

编写一个程序,用户输入两个数,求出其加减乘除,并用消息框显示计算结果 import javax.swing.JOptionPane; public class Test{ public static void main(String[] args) { int n1=Integer.parseInt(JOptionPane.showInputDialog("Input number 1: ")); int n2=Integer.parseInt(JOptionPane.showInpu

Quick-Select 1亿个数快速求第K小的数 分治法

Quick-Select  1亿个数快速求第K小的数  分治法 利用快速排序的思想,一开始选取中枢元,然后左右调整,接着比对中枢元p和K的大小,如果 p+1 = k (数组从0开始), 那么a[p] 就是答案,因为在p之前的,肯定都是小于a[p]的, 在p之后的,肯定大于p, 所以 a[p] 就是第 p+1 小.假如 p+1 不等于K, 那么根据大小,进行左右调整.调整过程中,理想状态下,每次都砍掉一半,数组的起始坐标要进行调整. 代码: // 快速排序法的修改 #include <iostre

【C++】输入8个数,求出最大值与最小值

//输入8个数,求出最大值与最小值 #include <iostream> using namespace std; int max(int b[],int n),min(int b[],int n); int main() { int a[8]; cout<<"输入8个int型数 :"; for(int i=0;i<8;i++) cin>>a[i]; cout<<"最大数为 "<<max(a,8)&