The factorial of an integer N, written N!, is the product of all the integers from 1 through N inclusive. The factorial quickly becomes very large: 13! is too large to store in a 32-bit integer on most computers, and 70! is too large for most floating-point variables. Your task is to find the rightmost non-zero digit of n!. For example, 5! = 1 * 2 * 3 * 4 * 5 = 120, so the rightmost non-zero digit of 5! is 2. Likewise, 7! = 1 * 2 * 3 * 4 * 5 * 6 * 7 = 5040, so the rightmost non-zero digit of 7! is 4.
PROGRAM NAME: fact4
INPUT FORMAT
A single positive integer N no larger than 4,220.
SAMPLE INPUT (file fact4.in)
7
OUTPUT FORMAT
A single line containing but a single digit: the right most non-zero digit of N! .
SAMPLE OUTPUT (file fact4.out)
4
思路:就是求余,不过要注意2和5的影响,因为没有2和5的影响乘积的个位必不为0,也就是答案,但要是有2和5的话有可能产生多重进位
如:25*104=2600 进了两位,若直接逐个求余,得到答案将是2,但正确答案是6(随便举个,本题阶乘可能不存在这数据,但可能存在类似的的多重进位)
因此,我选者将2和5的个数用two,five存下来,而相同的2,5个数会产生进位但不影响余数,除去2,5相同的个数后再乘上前面处理的余数(除去2,5的数)求余就是答案
具体代码:
/*
ID:nealgav1
LANG:C++
PROG:fact4
*/
#include<fstream>
#include<cstring>
using namespace std;
ifstream cin("fact4.in");
ofstream cout("fact4.out");
const int mm=5200;
const int _two[]={6,2,4,8,6,2,4,8};///乘2的余数
int ans[mm];///除去2,5模10的余数
int main()
{
int m,mid,two=0,five=0;///记录2,5的总个数
cin>>m;
ans[1]=1;mid=2;
for(int i=2;i<=m;i++)
{
mid=i;
/**除去2,5并记录*/
while(mid%2==0)
{
two++;mid/=2;
}
while(mid%5==0)
{
five++;mid/=5;
}
ans[i]=(ans[i-1]*mid)%10;
}///乘上2,5取余的答案
if(two>five)
{
two-=five;
ans[m]=(ans[m]*_two[two%4])%10;
}
else if(two<five)
{
ans[m]=(ans[m]*5)%10;
}
cout<<ans[m]<<"\n";
}
USER: Neal Gavin Gavin [nealgav1] TASK: fact4 LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 3376 KB] Test 2: TEST OK [0.000 secs, 3376 KB] Test 3: TEST OK [0.000 secs, 3376 KB] Test 4: TEST OK [0.000 secs, 3376 KB] Test 5: TEST OK [0.000 secs, 3376 KB] Test 6: TEST OK [0.000 secs, 3376 KB] Test 7: TEST OK [0.000 secs, 3376 KB] Test 8: TEST OK [0.000 secs, 3376 KB] Test 9: TEST OK [0.000 secs, 3376 KB] Test 10: TEST OK [0.000 secs, 3376 KB] All tests OK.YOUR PROGRAM ('fact4') WORKED FIRST TIME! That's fantastic -- and a rare thing. Please accept these special automated congratulations.
Here are the test data inputs:
------- test 1 ---- 1 ------- test 2 ---- 2 ------- test 3 ---- 7 ------- test 4 ---- 14 ------- test 5 ---- 143 ------- test 6 ---- 645 ------- test 7 ---- 777 ------- test 8 ---- 888 ------- test 9 ---- 999 ------- test 10 ---- 1000Keep up the good work!
Russ Cox
The insight for this problem is that 0's at the end of a number come from it being divisible by 10, or equivalently, by 2 and 5. Furthermore, there are always more 2s than 5s in a factorial.
To get the last digit of the factorial, we can run a loop to calculate it modulo 10, as long as we don't include any 2s or 5s in the product. Of course, we want to exclude the same number of 2s and 5s, so that all we're really doing is ignoring 10s. So after the loop, we need to multiply in any extra 2s that didn't have 5s to cancel them out.
/* PROG: fact4 ID: rsc001 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> void main(void) { FILE *fin, *fout; int n2, n5, i, j, n, digit; fin = fopen("fact4.in", "r"); fout = fopen("fact4.out", "w"); assert(fin != NULL && fout != NULL); fscanf(fin, "%d", &n); 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; fprintf(fout, "%d\n", digit); exit(0); }