一个小题目分析

网上朋友聊天,随便出了个简单的题目。对一个正整数(不含0)进行因数分解。要求:
输入:100
输出:2 * 2 * 5 * 5 = 100

输入:13
输出:13 = 13

很简单的一个题目。时间有限,只给十分钟。
很快,被问者给出答案:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    int m = 0;
    int i = 2;
    printf("\n请输入:");
    scanf("%d",&m);
    for(;i<m;i++)
    {
        if(m%i == 0)
        {
            printf("%d",i);
            if(m/i!=1)
                printf("*");
            m=m/i;
            i=1;
        }
        

    }
    return 0;
}

这个代码基本完成了目标。(但输出格式是不对,输入1也有问题)。继而又问,如何优化该代码。使得运算速度增加。
这个问题看似难回答,其实还是比较好回答的。因为这段代码里只有一个循环,无非是如何减少循环的次数。
第一个办法,对于一个给定的整数A, 其平方根为r, r = sqrt(A)。那么,如果被小于r的整数整除,必然产生一个比r大的整数。如果被r大的整数整除,必然产生一个比r小的整数。
所以,没必要从2一直循环到m,只要循环到 r就可以了。如果都没有被整数,那么此数必然是个质数。
第二个办法,质数除了2是偶数之外,没第二个偶数了。所以,在原来r的基础上,又可以少上大约一半的循环。所以这个代码改为:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    int m = 0, d;
    int i = 2;
    printf("\n请输入:");
    scanf("%d",&m);
    d = m;
    while (m >= 1)
    {
        if(m % i == 0)
        {
            printf("%d",i);
            m= m / i;
            if(m != 1)
                printf("*");
            i = 2;
        }
        else
        {
            if (i * i > m)

            {

               if (m != 1)//感谢weiMMXfighting朋友的指正

                printf("%d", m);

                break;
            }
            i++;
            i |= 0x01;
        }
    }
    printf(" = %d\n", d);
    return 0;
}

对于内部含有大质数的合数来说,这个代码循环数会大大减少。比如说:994这个数,循环10次即可用第二种算法分解完毕;用第一种,大约需要循环70多次。所含质数越大,效果越明显。如果把从1到1000000的数全部分解。速度会有明显的差异。

第三种办法,质数的数量是比较稀少的,可以建立一个表,直接除表里的数就可了。不过,这个要事先计算,需要一定的空间存储。也可以在计算过程中动态生成质数表,不过这个不适合对单个整数的分解,适合对一大批数进行分解。

你可能感兴趣的:(一个小题目分析)