NEFU118 n!后面有多少个0【算术基本定理】

题目链接:

http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=118

题目大意:

问:计算N!末尾0的个数。(1 <= N <= 1000000000)。

思路:

N是100000000规模的数,直接计算结果,再统计0的个数显然不科学。将末尾0分解为2*5。

每一个0必然和一个因子5对应,但是一个数的因式分解中一个因子5不一定对应一个0。因为

还需要一个因子2,才能实现一一对应。

对于N!,在因式分解中,因子2的个数明显大于因子5的个数。所以如果存在一个因子5,那么

必然对应着N!末尾的一个0。这道题就变为了求N!中因子5的个数。由算术基本定理的性质(5)

可知:N!在素因子分解中素数p的幂为[N/p] + [N/p^2] + [N/p^3] + …,可以直接循环计算。

此时,5的幂就是N!中因子5的个数,也就是N!末尾0的个数。

附算术基本定理的定义和性质:

定理:

每个大于1的正整数N都可以被唯一地写成素数的乘积,在乘积中的素因子按照非降序排列。

正整数N的分解式 N = p1^α1 * p2^α2 * p3^α3 * … * pk^αk 称为N的标准分解式,其中

p1,p2,…,pk是素数,p1 < p2 < p3 < … < pk,且α1,α2,α3,…,αk是正整数。

性质:

(1)若N的标准素因子分解表达式为:N = p1^α1 * p2^α2 * p3^α3 * … * pk^αk,设d(N)

为N的挣银子个数, Φ(N)为N的所有因子之和,则有

d(N) = (α1 + 1) * (α2 + 1)
* (α3 + 1) * … * (αk + 1)

Φ(N) = ( p1^(α1
+ 1) )/(p1 - 1) * ( p2^(α2 + 1) )/(p2
- 1) * … * ( pk^(αk + 1) )/(pk - 1)

(2)设a =
p1^α1 * p2^α2 * … * pk^αk,b = p1^ β1
* p2^β2 * … * pk^βk,则有

gcd(a,b) = p1^min(α1,β1) * p2^min(α2,β2)
* … * pk^min(αk,βk)

lcm(a,b) = p1^max(α1,β1)
* p2^max(α2,β2)
* … * pk^max(αk,βk)

(3)如果a和b为实数,则

max( gcd(a,b) ) + min( gcd(a,b) ) = a + b

(4)如果a和b是正整数,则

lcm(a,b) = a*b/gcd(a,b)

(5)N!的素因子分解中的素数p的幂为

[N/p] + [N/p^2] + [N/p^3] + …

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

int main()
{
    int T,N;
    cin >> T;
    while(T--)
    {
        cin >> N;
        int t,five,sum;
        t = N;
        five = 5;
        sum = 0;
        while(five <= t)
        {
            sum = sum + t/five;
            five *= 5;
        }
        cout << sum << endl;
    }

    return 0;
}
时间: 2024-12-13 12:00:16

NEFU118 n!后面有多少个0【算术基本定理】的相关文章

nefu 118 n!后面有多少个0 算数基本定理,素数分解

n!后面有多少个0 Time Limit 1000ms Memory Limit 65536K description 从输入中读取一个数n,求出n!中末尾0的个数. input 输入有若干行.第一行上有一个整数m,指明接下来的数字的个数.然后是m行,每一行包含一个确定的正整数n,1<=n<=1000000000. output 对输入行中的每一个数据n,输出一行,其内容是n!中末尾0的个数. sample_input 3 3 100 1024 sample_output 0 24 253 考

nefu 118 n!后面有多少个0(算数基本定理)

题意:从输入中读取一个数n,求出n!中末尾0的个数. 思路:阶乘后的数很大,不可能直接计算的,对于任意一个正整数,若对其进行因式分解,那么其末尾的0必定可以分解为2*5,在这里,每一个0必然和一个因子5对应,但是注意,一个数的因式分解中的因子5不一定对应着一个0,因为还需要一个2呢,对于n!,在饮食分解中,2的因子个数要大于5的因子个数,所以如果存在一个因子5,那么它必然对应着n!末尾的一个0,本题便变为了 求 因子5的个数,有因为5是素数,所以可以用到算术基本定理的 n!的素数因子分解中的素数

唯一分解定理(算术基本定理)及应用

算术基本定理:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积 N = p1^a1 * p2^a2 * p3^a3 * ... * pn^an (其中p1.p2.... pn为N的因子,a1.a2.... .an分别为因子的指数) 这样的分解称为 N 的标准分解式 应用: (1)一个大于1的正整数N,如果它的标准分解式为: N = p1^a1 * p2^a2 * p3^a3 * ... * pn^an (2)N的因子个数     M(N)= (1 + a1)*(1

NEFU119 组合素数【算术基本定理】

题目链接: http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=119 题目大意: 给你两个整数N和P,求出C(2*N,N)被素数p整数的次数. 思路: 由算术基本定理的性质(5)可得到N!被素数P整除的次数. 来看这道题,C(2*N,N) = (2*N)! / (N! * N!).最终结果就是从(2*N)!能被素数P整除的 次数里边减去N!能被素数整除的次数*2.最终结果为: [2*N/P] + [2*N/P^2] + -

light_oj 1347 算术基本定理

light_oj 1347 算术基本定理 C - Aladdin and the Flying Carpet Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1341 Description It's said that Aladdin had to solve seven mysteries before getting the M

算术基本定理 求一个数的约数个数

算术基本定理  求一个数的约数个数 算术基本定理: 分解素因数:n=(p1^k1)*(p2^k2)*...*(pn*kn).(分解方式唯一) n的约数个数为cnt(n)=(1+k1)*(1+k2)*...*(1+kn). bool isprime[maxn]; vector<int> prime; void play_prime() { memset(isprime,1,sizeof(isprime)); isprime[1]=0; for(int i=2;i<maxn;i++){ if

51nod 1189 算术基本定理/组合数学

www.51nod.com/onlineJudge/questionCode.html#!problemId=1189 1189 阶乘分数 题目来源: Spoj 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 1/N! = 1/X + 1/Y(0<x<=y),给出N,求满足条件的整数解的数量.例如:N = 2,1/2 = 1/3 + 1/6,1/2 = 1/4 + 1/4.由于数量可能很大,输出Mod 10^9 + 7. Input 输入一个数N

poj 1845 Sumdiv (算术基本定理求一个数因子和)

求一个数的所有因子和可以用算术基本定理,下面是它的两个重要应用: (1)一个大于1的正整数N,如果它的标准分解式为: N=(P1^a1)*(P2^a2)......(Pn^an) 那么它的正因数个数为(1+a1)(1+a2).....(1+an). (2) 它的全体正因数之和为d(N)=(1+p1+...p1^an)(1+p2+...p2^a2)...(1+pn+...+pn^an) 和求一个数正因数个数的方法类似. 可以先打表出sqrt(n)以内的所有素数(当然也可以不打表),因为n的素因数中

HDU 1142 Factorial ( 算术基本定理 + 分解N! )

HDU 1142 Factorial ( 算术基本定理 + 分解N! ) #include <cstdio> int main() { int t, n; scanf( "%d", &t ); while( t-- ) { scanf( "%d", &n ); int cnt = 0; while( n ) { cnt += n/5; n /= 5; } printf( "%d\n", cnt ); } return