1. 程式人生 > >之江學院 K: qwb與小數(思維求A/B第n位小數)

之江學院 K: qwb與小數(思維求A/B第n位小數)

記得不久前的一場實驗室收錢大賽中,出現了一個六位有效數字,以及迷之坑點0 , 0 的資料,jnf這次吸取了教訓,所以。。。他準備再卡一下小數點。當然此題不會太難,jnf友情的提示學弟學妹們,這題。。是很簡單(^_^)的!

jnf遇到了一個問題:將分數a/b化為小數後,小數點後第n位的數字是多少?

因為這是第一道題,我們已經不指望你能夠幫上他了。。。

當然如果你們暴力過了,算我jnf輸!

多組測試資料,處理到檔案結束。(測試資料<=10組)

每組測試例包含三個整數a,b,n,相鄰兩個數之間用單個空格隔開,其中0 <= a <1e8,0 < b <= 1e8,1 <= n <= 1e8。

對於每組資料,輸出a/b的第n位數,佔一行

1 2 1
1 2 2
5
0
該題目是求a/b的小數點後的第n位數字是啥?面對該題目,你首先想到的是按照題目的思路一步一步的走向錯誤,第一步根本就不能先a/b,
因為如果轉換成double型的小數,在求第n位小數是什麼的時候,會出現精度的誤差:

C語言裡面,預設%f是小數點後6位,如果想小數點後面16位,寫成%.16lf
不會自動四捨五入的,double是一個近似值,通常沒有辦法做的很精確.
通常能精確到小數點後面5,6位,也就是說超過5,6位了可能就不準了。


所以這個題目需要轉化思路,即將等式兩邊同時乘以10^n,即可得到,接下來我的思路是這樣的:
求a*(10^n),然後對10取餘,即可得到第n位小數,但是wa了,我還不知道為什麼。

經過斌爺的指導我終於找到了原因:因為10的n次方早就超過了long long的範圍,肯定會炸,所以會想到取模,但是除法這怎麼
取模呢:
(a/b)%mod=a%(b*mod)/b%mod;
這個題目太水了,因為資料太小了,這種方法只要正確取模都能通過,但是原題資料是1e9,那麼這種方法10^n即使取模
,也會爆掉,所以只能用下面的這種方法。


正確求解是:
模擬除法,但是和有區別,原因是此題不需要求出商的每一位是什麼,只需要找出某一位商是什麼,那麼就用到了一種方法:對不需要求出的
位,只需要保留除法之後的餘數就行了,用%b來實現,進行到下一位那麼則需要*10來實現,當實現到要求的某位的前一位的時候,則需要停止,
此時要做的就是實現最後一位,需要*10並且/b。轉化成程式碼,如下:

既然10^n取模會爆掉,那就求n-1次方,最後再乘上10,這樣中間取模就不會爆掉。

#include<stdio.h>
#include<string.h>
#include<math.h>
int b;
long long quick(long long a,long long c)
{
    long long ans=1;
    while(c!=0)
    {
        if(c&1)
            ans=ans*a%b;
        a=a*a%b;
        c=c/2;
    }
    return ans%b;
}
int main()
{
    int a,n;
    while(~scanf("%d%d%d",&a,&b,&n))
    {
        long long len=(a%b*quick(10,n-1))%b;
        long long ans=10*len/b;
        printf("%lld\n",ans);
    }
}