Last non-zero Digit in N! HDU - 1066
題意:
求n!的最后一位非零數(shù)。
題目:
The expression N!, read as “N factorial,” denotes the product of the first N positive integers, where N is nonnegative. So, for example,
N N!
0 1
1 1
2 2
3 6
4 24
5 120
10 3628800
For this problem, you are to write a program that can compute the last non-zero digit of the factorial for N. For example, if your program is asked to compute the last nonzero digit of 5!, your program should produce “2” because 5! = 120, and 2 is the last nonzero digit of 120.
Input
Input to the program is a series of nonnegative integers, each on its own line with no other letters, digits or spaces. For each integer N, you should read the value and compute the last nonzero digit of N!.
Output
For each integer input, the program should print exactly one line of output containing the single last non-zero digit of N!.
Sample Input
1
2
26
125
3125
9999
Sample Output
1
2
4
8
2
8
分析:參考
我們發(fā)現(xiàn)n!末尾的0都是通過(guò)5和2想成得到的,為了把0去掉,我們把所有的因數(shù)2和5都提出來(lái),放到最后再處理。
我們?cè)O(shè)F(N)表示N!的尾數(shù)。
先考慮簡(jiǎn)單的。考慮某一個(gè)N!(N < 10),我們先將所有5的倍數(shù)提出來(lái),用1代替原來(lái)5的倍數(shù)的位置。由于5的倍數(shù)全被提走了,所以這樣就不會(huì)出現(xiàn)尾數(shù)0了。我們先把0?90-90?9的階乘的尾數(shù)列出來(lái)(注意,5的倍數(shù)的位置上是1),可以得到table[0—9]=(1, 1, 2, 6, 4, 4, 4, 8, 4, 6)。對(duì)于N < 5,直接輸出table[N]即可;對(duì)于N>=5,由于提出了一個(gè)5,因此需要一個(gè)2與之配成10,即將尾數(shù)除以2。注意到除了0!和1!,階乘的最后一個(gè)非零數(shù)字必為偶數(shù),所以有一個(gè)很特別的除法規(guī)律:2/2=6,4/2=2,6/2=8,8/2=42/2=6,4/2=2,6/2=8,8/2=42/2=6,4/2=2,6/2=8,8/2=4。比較特殊的就是2/2=12/2=6,6/2=16/2=82/2=12/2=6,6/2=16/2=82/2=12/2=6,6/2=16/2=8.這樣我們就可以得到如下式子:F(N)={2N/5table[N](0<=N<10)F(N)=\left \{ ^{table[N]}_{ 2^{N/5}} \right.(0 <= N < 10)F(N)={2N/5table[N]?(0<=N<10)
- 再考慮復(fù)雜的。考慮某一個(gè)N!(N>=10),我們先將所有5的倍數(shù)提出來(lái),用1代替原來(lái)5的倍數(shù)的位置。由于5的倍數(shù)全被提走了,所以這樣就不會(huì)出現(xiàn)尾數(shù)0了。我們觀察一下剩下的數(shù)的乘積的尾數(shù),通過(guò)table表,我們發(fā)現(xiàn)這10個(gè)數(shù)的乘積的尾數(shù)是6,6*6的尾數(shù)還是6,因此我們將剩下的數(shù)每10個(gè)分成一組,則剩下的數(shù)的乘積的尾數(shù)只與最后一組的情況有關(guān),即與N的最后一位數(shù)字有關(guān)。(因?yàn)楦鶕?jù)最后一位就能知道它在尾數(shù)表中處于第幾個(gè)位置,只要將尾數(shù)表之前的數(shù)相乘就得到最后一組的尾數(shù)。)由于我們把5的倍數(shù)提出來(lái)了,N!中一次可以提出[N/5]個(gè)5的倍數(shù),有多少個(gè)5,就需要有多少個(gè)2與之配成10,所以有多少個(gè)5,最后就要除以多少個(gè)2。注意到除2的結(jié)果變化是4個(gè)一循環(huán),因此如果有A個(gè)5,只需要除(A MOD 4)次2就可以了。A MOD 4只與A的最后兩位數(shù)有關(guān),很好求算。剩下的5的倍數(shù),由于5已經(jīng)全部處理掉了,就變成[N/5]!。于是,我們可以得到
一個(gè)遞歸關(guān)系:
F(N)={2[N/5]mod4F[N]?table[N的尾數(shù)]?6(N>10)F(N)=\left \{ ^{F[N]*table[N的尾數(shù)]*6}_{ 2^{[N/5] mod 4}} \right.(N >10)F(N)={2[N/5]mod4F[N]?table[N的尾數(shù)]?6?(N>10)
這樣我們就得到了一個(gè)O(log5(N))的算法,整除5可以用高精度加法做,乘2再除10即可。整個(gè)算法相當(dāng)巧妙。
AC代碼:
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int M=1e3+10; const int mp[20]= {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2}; char s[M]; int main() {while(~scanf("%s",s)){int n=strlen(s),ret=1,a[M];if(n==1)printf("%d\n",mp[s[0]-'0']);else{for(int i=0; i<n; i++)a[i]=s[n-1-i]-'0';while(n>1){if(a[n-1]==0)n--;ret=ret*mp[a[1]%2*10+a[0]]%5;int num=0;for(int i=n-1; i>=0; i--)//num=num/5{num=num*10+a[i];a[i]=num/5;num%=5;}}printf("%d\n",ret+ret%2*5);}}return 0; }如何求n!中5的個(gè)數(shù)
int get5(int n)//計(jì)算n!中質(zhì)因子5的出現(xiàn)次數(shù) {if(n==0)return 0;return n/5+get5(n/5); }總結(jié)
以上是生活随笔為你收集整理的Last non-zero Digit in N! HDU - 1066的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 提现游戏的千层套路提现游戏的千层套路是什
- 下一篇: 云游戏真有那么大魅力云游戏真有那么大魅力