日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu1066

發布時間:2024/4/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu1066 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

摘自:http://blog.sina.com.cn/s/blog_59e67e2c0100a7yx.html

需要慢慢注墨。。。。

首先引用下leemars的報告:

這道題要求N!的最后一個非0數字是多少,如果用一般作法,先統計2和5的個數,然
后補乘2,得到的將是TLE。所以還需要再做簡化:

為了把0去掉,我們把所有的因數2和5都提出來,放到最后再處理。N!中的N個相乘的
數可以分成兩堆:奇數和偶數。偶數相乘可以寫成(2^M)*(M!),M=N DIV 2。M!可以
遞歸處理,因此現在只需討論奇數相乘。考慮1*3*5*7*9*11*13*15*17* ... *N(如果
N為偶數則是N-1),這里面是5的倍數的有5,15,25,35,... ,可以其中的5提出來
,變成(5^P)*(1*3*5*7*9* ... ),后面括號中共P項,P=(N DIV 5+1) DIV 2,而后
面的括號又可以繼續提5出來,遞歸處理。現在剩下的數是1 * 3 * 7 * 9 * 11 * 13
* 17 * 19 * ... 。這些數我們只需要他們的個位數,因為(1 * 3 * 9 * 11 * 13
* ... ) MOD 10 = (1 * 3 * 7 * 9 * 1 * 3 * ... ) MOD 10。我們列出余數表,
1 3 1 9 9 7 9 1 1 3 1 9 9 7 9 ……。我們發現每八項MOD 10的結果是一個循環。
算出奇數的結果后,我們再回頭看統計了多少個2和5需要乘入。把2和5配對完都是N
!后面的0,看剩下的2有幾個。如果有剩下的2,考慮2^N的個位數又是2 4 8 6 2 4
8 6 ……每四項一個循環,找出這個個位數后,和前面的結果相乘,再取個位數就是
答案。由于我們完全把2和5的因素另外處理,所以在所有的乘法中,都只需要計算個位數乘法,并且只保留個位數的結果。

但讓我很驚異的是:為什么我提交總是WA?后來我才知道,原因是這道題的N相當大
!達到了10^100!要用大數來處理!GPC四項編譯開關全關的,自然查不出來!而且
上面這個算法換成大數后會很麻煩。還有什么別的好方法嗎?

答案是有的。我們設F(N)表示N!的尾數。

先考慮簡單的。考慮某一個N!(N < 10),我們先將所有5的倍數提出來,用1代替原來
5的倍數的位置。由于5的倍數全被提走了,所以這樣就不會出現尾數0了。我們先把
0..9的階乘的尾數列出來(注意,5的倍數的位置上是1),可以得到table[0..9] =
(1, 1, 2, 6, 4, 4, 4, 8, 4, 6)。對于N < 5,直接輸出table[N]即可;對于N >
= 5,由于提出了一個5,因此需要一個2與之配成10,即將尾數除以2。注意到除了0
!和1!,階乘的最后一個非零數字必為偶數,所以有一個很特別的除法規律:2 / 2
= 6,4 / 2 = 2,6 / 2 = 8,8 / 2 = 4。比較特殊的就是2 / 2 = 12 / 2 = 6,
6 / 2 = 16 / 2 = 8。這樣我們就可以得到如下式子:
代碼:

? ? ? table[N]
F(N) = ------------ (0 <= N < 10)
? ? ? 2^([N/5])

再考慮復雜的。考慮某一個N!(N >= 10),我們先將所有5的倍數提出來,用1代替原
來5的倍數的位置。由于5的倍數全被提走了,所以這樣就不會出現尾數0了。我們觀
察一下剩下的數的乘積的尾數,通過table表,我們發現這10個數的乘積的尾數是6,
6 * 6的尾數還是6,因此我們將剩下的數每10個分成一組,則剩下的數的乘積的尾數
只與最后一組的情況有關,即與N的最后一位數字有關。由于我們把5的倍數提出來了
,N!中一次可以提出[N/5]個5的倍數,有多少個5,就需要有多少個2與之配成10,所
以有多少個5,最后就要除以多少個2。注意到除2的結果變化是4個一循環,因此如果
有A個5,只需要除(A MOD 4)次2就可以了。A MOD 4只與A的最后兩位數有關,很好求
算。剩下的5的倍數,由于5已經全部處理掉了,就變成[N/5]!。于是,我們可以得到
一個遞歸關系:
代碼:

? ? ? F([N/5]) * table[N的尾數] * 6
F(N) = ----------------------------------- (N > 10)
? ? ? ? ? 2^([N/5] MOD 4)

這樣我們就得到了一個O(log5(N))的算法,整除5可以用高精度加法做,乘2再除10即
可。整個算法相當巧妙,寫起來也比較輕松。

?因為 2^N 是以4為循環節的

而且table[N]是以10為循環節的

所以從10開始

???? F([N/5]) * table[N的尾數] * 6
F(N) = ----------------------------------- (N > 10)
? ? ? ? ? 2^([N/5] MOD 4)

右邊的式子除了F[n/5]外 是以20為循環節的

寫出循環的末尾數字mod[20]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2}

整體思路解決了

然后就開始編程序嘍!

#include<stdio.h>
#include<string.h>
int mod[20]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};
char n[1000];
int a[1000];
int main()
{
?int i,c,t,len;
??? while(scanf("%s",n)!=EOF)
?{
??t=1;
??len=strlen(n);?
??for(i=0;i<len;i++)
???a[i]=n[len-1-i]-'0';
??while(len)
??{
???len-=!a[len-1];
???t=t*mod[a[1]%2*10+a[0]]%10;??
???for(c=0,i=len-1;i>=0;i--)??????
????c=c*10+a[i],a[i]=c/5,c%=5;
??}
??printf("%d\n",t);
?}
?return 0;
}

轉載于:https://www.cnblogs.com/FCWORLD/archive/2011/04/20/2022602.html

總結

以上是生活随笔為你收集整理的hdu1066的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。