USACO Factorials

1、做到这么水的题真感动啊。。。刚开始以为要用高精度乘法,吓坏了。。。其实不用,只要保留最后几位就可以了(注意不是保留最后一位),因为可能与两位数相乘的时候,前面进位使得最后为0,要是不保存前几位,乘后的结果就不对了。。。

2、还要注意,最后输出的时候只输出一位。。。我刚开始忘了,WA一次。。。

/*
ID:mrxy564
PROG:fact4
LANG:C++
*/
#include<cstdio>
using namespace std;
int main(){
 freopen("fact4.in","r",stdin);
 freopen("fact4.out","w",stdout);
    int n,ans=1;
 scanf("%d",&n);
 for(int i=1;i<=n;i++){
          ans*=i;
          while(ans%10==0) ans/=10;
    ans%=10000;
 }
 printf("%d\n",ans%10);
 return 0;
}

官方题解:

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);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值