末位零问题(换种思路,问题能被无限倍的简化,这就是算法的魅力!)

来源:互联网 发布:软件自学网创办人 编辑:程序博客网 时间:2024/05/21 11:00

问题:

函数  f(x)

表示   x 末位零的个数,例如f(1200)=2f(1234)=0

现在已知   n   ,k。n<2^31  k<9

求 min(z)  f(z)=k   且z%n=0。


输入:

多组输入,每组两个整数

输出:

每组输出一个答案占一行。


刚开始是这样想的

#include <stdio.h>int pow1(int a,int  b) //定义快速幂函数{    int t=1,m=a;    while(b!=0)    {        if(b&1==1) t*=m;        m*=m;        b>>=1;    }    return t;}int main(){        int n,k,a,b;             int i;        while(scanf("%d %d",&n,&k)!=EOF)  // k表示一个数末尾 0 的个数, n是这个数的约数                                          //  求出这个数的最小值。。        {            i= 2;            a=pow1(10,k);   // 首先满足末尾有k个0 的最小值  肯定是10的k次方            b=a;            while(i != 0)            {            if(b%n == 0)   //判断这个数是不是n的倍数            {                printf("%d\n",b);  //如果是  就输出这个数                break;            }            else                // 如果不是            {                b=a*i;         //  就依次把这个数乘2、3、4、5……一直到是n的倍数为止                i++;            }            }        }                             return 0;}
  这样写答案一定是对的,但是如果k=0,n=2^30  就要循环2^30次方次!!!显然要超时!!!的!!!

下是一种很巧妙的方法!

灵活的运用打表,gcd,!

仔细想下题的意思,要求的z就是 n 和 10^k的最小公倍数吧!!!

能想到这里就简单了!!!


typedef long long LL;    LL gcd(LL a, LL b)                         //定义gcd函数{    return b!=0 ? gcd(b, a % b) : a;}int main(){    int i;    LL n, k, res[10];    res[0] = 1;    for(i = 1; i < 10; ++i)                 {        res[i] = res[i - 1] * 10;      //数组赋值 10^0--10^9,因为k最大是9哈!    }    while(scanf("%lld %lld", &n, &k) != EOF)    {        printf("%lld\n", n * res[k] / gcd(n, res[k]));//   求最小公倍数  ,也就是z    }    return 0;                                      // 不论k的值是多少,直接出答案!!}

换种思路,问题能被无限倍的简化,这就是算法的魅力!

n,k

n<231,k<9

阅读全文
0 0