The Last Non-zero Digit POJ - 1150(n!mod p)
題意:
要求你求出n!(n?m)!)\frac{n!}{(n-m)!)}(n?m)!)n!?中最后一個非0的數字.
題目:
In this problem you will be given two decimal integer numberN,M. You will have to find the last non-zero digit of the NPM^{N}P_{M}NPM?.This means no of permutations of N things taking M at a time.
Input
The input contains several lines of input. Each line of the input file contains two integers N (0 <= N<= 20000000), M (0 <= M <= N).
Output
For each line of the input you should output a single digit, which is the last non-zero digit of NPM. For example, if NPM^{N}P_{M}NPM? is 720 then the last non-zero digit is 2. So in this case your output should be 2.
Sample Input
10 10
10 5
25 6
Sample Output
8
4
2
分析:
說實話這道題上來我就沒看懂題意,這怎么就NPM^{N}P_{M}NPM?==n!(n?m)!)\frac{n!}{(n-m)!)}(n?m)!)n!?了?In a word ,我感覺到了不友好。
然后我就開始了啃書環節,具體在《挑戰程序設計》P293,之后惡意鋪面而來,花費我一晚上,終于摸透了這個題,必須滴好好說道說道。
(1)首先是若求n!的最后一位,我們可以將所有的因數10去掉,問題就轉換為了求這個數的最后一位。根據以往的做題經驗,這時候只要找到所有的因子2和5,放著對最后特判對于最后一位的影響就好了,所以正常while循環暴力找因子數,然后超時了,代碼如下:
這并不冤枉,其實開數組2e7就該知道有問題,試了編譯器,可以運行,就硬著頭皮寫下來了,不出意料,果真超時了。那這里就用到了“白書”的定理,我懶得敲了。
具體代碼如下:
(2)當我們對(1~n)去除因子2,5后發現最后一位的值,只可能是 1,3, 7,9這四個數,因為最后一位若為1,n!相乘對最后一位值的變化沒有影響,所以可以不用考慮,只考慮 3,7 ,9,即可。這時發現了規律,例如,即當存在多個3時,只考慮個位值,出現了循環節{1,3,9,7},注意第一位為整除時,所以為值為1。你以為到這就算完了,還不夠!
(3)如上超時代碼,不能打表開數組存,所以每次輸入就直接調用函數,直接對n!進行討論,將其分為奇偶兩個部分:
【1】對于偶數序列,我們只需將它除 2 即可遞歸轉化為奇數序列(其實就是消去因子2)。
【2】對于奇數序列,我們可以發現,每 10個數字中就有 3 , 7 , 9 各一個,但又因為(1~n)中有 5的倍數,所以繼續除 5,遞歸消去因子。
(4)這里就差不多了,但還是要注意:
一,當因子2的個數小于5的個數時,由于此時末尾必為奇數(1,3,7,9中一個),所以相乘最后一位必為5,直接輸出。
二,當因子2的個數大于5的個數時,需要考慮因子2對結果的一個影響,這時也有與前面一樣的規律{6,2,4,8},理解了之后讓我們歡樂敲代碼吧;
AC模板:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int n,m; int e[4][4]={{6,2,4,8},{1,3,9,7},{1,7,9,3},{1,9,1,9}}; int sum(int n,int p){//計算n!中質因子m的出現次數,用到“挑戰程序設計”P293推論return n==0?0:n/p+sum(n/p,p); } int odd(int n,int p){//奇數數列中末尾為x的數出現的次數,消去1~n數中存在的因子5return n==0?0:n/10+(n%10>=p)+odd(n/5,p); } int even(int n,int p){//末尾為x的數的出現次數,消去1~n數中存在的因子2;return n==0?0:even(n/2,p)+odd(n,p); } int main() {while(~scanf("%d%d",&n,&m)){int su=sum(n,2)-sum(n-m,2);int sm=sum(n,5)-sum(n-m,5);int a=even(n,3)-even(n-m,3);int b=even(n,7)-even(n-m,7);int c=even(n,9)-even(n-m,9);if(su<sm){printf("5\n");continue;}int ans=e[1][a%4]*e[2][b%4]*e[3][c%4]%10;if(su!=sm)ans*=e[0][(su-sm)%4];printf("%d\n",ans%10);}return 0; }備戰ccpc分站賽ing ,題目分析簡略,見諒,轉載請注明出處。。。。。
總結
以上是生活随笔為你收集整理的The Last Non-zero Digit POJ - 1150(n!mod p)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Circle and Points PO
- 下一篇: 蓝桥杯2014届试题9题 小朋友排队(树