Just the Facts
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 any factorial for (). 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 not exceeding 10000, 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. Each line of output should contain the value N, right-justified in columns 1 through 5 with leading blanks, not leading zeroes. Columns 6 - 9 must contain `` -> " (space hyphen greater space). Column 10 must contain the single last non-zero digit of N!.
Sample Input
1
2
26
125
3125
9999
Sample Input
1
2
26
125
3125
9999
Sample Output
1 -> 1
2 -> 2
26 -> 4
125 -> 8
3125 -> 2
9999 -> 8
看到這個題的第一想法就是用求大數階乘的方法求出n的階乘,然後從最後一位開始找,直到找到一個非零的數輸出。
#include<stdio.h> #include<string.h> int a[30000]; int main() { int n,i,j,c,s; while(~scanf("%d",&n)) { memset(a,0,sizeof(a)); a[0]=1; for(i=2;i<=n;i++) { s=0; for(j=0;j<30000;j++) { c=a[j]*i+s; a[j]=c%10; s=c/10; } } for(i=0;;i++) if(a[i]) { printf("%5d -> %d\n",n,a[i]); break; } } return 0; }
提交以後是Time limit exceed!
後來看了大牛的代碼,才知道自己懂得太少了。下面是一種比較容易理解的代碼:
include<stdio.h> int main() { int n,s,i; while(scanf("%d",&n)==1) { for(i=1,s=1;i<=n;i++) { s*=i; while(s%10==0) s/=10; s=s%100000; } printf("%5d -> %d\n",n,s%10); } return 0; } #include<stdio.h> int main() { int n,s,i; while(scanf("%d",&n)==1) { for(i=1,s=1;i<=n;i++) { s*=i; while(s%10==0) s/=10; s=s%100000; } printf("%5d -> %d\n",n,s%10); } return 0; }
另外讓大家看一下大牛們的代碼:
代碼一:
include<stdio.h> int main() { int n,i,num; while(scanf("%d",&n)!=EOF) { num=1; for(i=1;i<=n;i++) { if(i%5==0) { int x=i; while(x%10==0) x/=10; while(x%5==0) { x/=5; num/=2; } num*=x; } else num*=i; num%=100000;/
/一定要至少保留後五位非零位(五位以上要注意int型溢出,因此取五位最佳),因為後五位非零位的進位(極限情況3125,即5^5)會影響到最後的非零位
}
printf("%5d -> %d\n",n,num%10);
}
return 0;
}
#include<stdio.h>
int main()
{
int n,i,num;
while(scanf("%d",&n)!=EOF)
{
num=1;
for(i=1;i<=n;i++)
{
if(i%5==0)
{
int x=i;
while(x%10==0)
x/=10;
while(x%5==0)
{
x/=5;
num/=2;
}
num*=x;
}
else
num*=i;
num%=100000;//一定要至少保留後五位非零位(五位以上要注意int型溢出,因此取五位最佳),因為後五位非零位的進位(極限情況3125,即5^5)會影響到最後的非零位
}
printf("%5d -> %d\n",n,num%10);
}
return 0;
}
代碼二:
[ include <stdio.h> int main() { int n2, n5, i, j, n, digit; while(scanf("%d",&n)!=EOF) { digit = 1; n2 = n5 = 0; for(i=2; i<=n; i++) { j = i; while(j%2 == 0) { n2++; j /= 2; } while(j%5 == 0) { n5++; j /= 5; } digit = (digit * j) % 10; } for(i=0; i<n2-n5; i++) digit = (digit * 2) % 10; printf("%5d -> %d\n",n,digit); } return 0; } #include <stdio.h> int main() { int n2, n5, i, j, n, digit; while(scanf("%d",&n)!=EOF) { digit = 1; n2 = n5 = 0; for(i=2; i<=n; i++) { j = i; while(j%2 == 0) { n2++; j /= 2; } while(j%5 == 0) { n5++; j /= 5; } digit = (digit * j) % 10; } for(i=0; i<n2-n5; i++) digit = (digit * 2) % 10; printf("%5d -> %d\n",n,digit); } return 0;
}從2到n,每次更新digit,都先求出該數的2和5的個數,每對2和5相互抵消,每次計算都對10取模,減小計算量。顯然2的個數一定比5的個數多。