1066 Last non-zero Digit in N!
题目做不出 看答案:参考文献
https://www.xuebuyuan.com/1394116.html
https://blog.csdn.net/orangesix/article/details/44190501(在下面的8/2还是什么 只要因子2的数量还有 都不会尾数绝对不会是奇数)
http://blog.sina.com.cn/s/blog_59e67e2c0100a7yx.html(里面讲了两种解法 第一种也是对一下第一种代码进行修改 ~但超时了)
https://blog.csdn.net/a601025382s/article/details/38174939
一开始想的是一直保留最后一位 只要是0 就把他去掉 这个代码一开始答案正确就没有去多想 然后提交失败后想了很久,发现我们只关心最后一位 却忘了前一位也是跟前一位的值有关系的 这样就导致了误解 一些需要两位数起作用 我们一直保留最后一位这个方法是错误的,一个数相乘答案跟其他位置都有密切联系。
例如 我们把98*5 答案是490 尾数正确是9 ,但是我们取尾数相乘的话 仅仅才4 这就是问题所在。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
long n = sc.nextLong();
long count = 1;
for (int i = 1; i <= n; i++) {
count *= i;
while (count % 10 == 0)
count /= 10;
count %= 10;
}
System.out.println(count);
}
}
}
所以要改用其他方法
https://baike.baidu.com/item/阶乘/4437932?fromtitle=n!&fromid=7806135
看了一整天 还是看不懂 突然睡着睡着想到了
//
// main.c
// HDOJ1066
//
// Created by Egger on 18/1/15.
// Copyright (c) 2015年 Egger. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#define SIZE 10
#define MAXH 1000
char Str[MAXH];
int Num[MAXH];
const int FirstTen[SIZE] = {1,1,2,6,4,2,2,4,2,8};
const int Table[SIZE] = {6,6,2,6,4,4,4,8,4,6};
const int DivisionCircle[4] = {2,6,8,4};
int H(int X, int Y)//y小于100 跟百位没有多大关系
{
int i;
for(i = 0; i < 4; i++)
{
if (X == DivisionCircle[i])
{
break;
}
}
return DivisionCircle[(i+Y)%4];
}
int F(char* s)
{
int i,k;
int Bit,Carry,Len,Result;
Len = (int)strlen(s);
Result = 1;
if(Len < 2)
{
return FirstTen[s[0]-'0'];
}
for(i = Len - 1; i >= 0; i--)
{
Num[Len-1-i] = s[i] - '0';
}
while(Len > 1)
{
k = Num[0];
Carry = 0;
Num[Len] = 0;
for(i = 0; i <= Len; i++)
{
Bit = Num[i] * 2 +Carry;//因为要把它传到(n/5!相当于*2/10)
Num[i] = Bit % 10;//适用于所有的数 别管被截掉的尾位
Carry = Bit / 10;
}
for(i = 1; i <= Len; i++)
{
Num[i-1] = Num[i];
}
if(Num[Len] == 0)
Len --;
Result = Result * H(Table[k], Num[0]+Num[1]*10) % 10;//因为每四位一个循环 所以跟百位以上没多大联系
}
Result = Result * FirstTen[Num[0]] % 10;
return Result;
}
int main(int argc, const char* argv[])
{
while(scanf("%s",Str) != EOF)
{
printf("%d\n",F(Str));
}
return 0;
}
~~整理很久的思路 终于想清楚了 ~ 改写成java 有不懂可以留言
import java.util.*;
public class Main {
static int num = 1000;//因为输入值位1000位的数 所以采用数组一个位一个位保存
static int FirstTen[] = { 1, 1, 2, 6, 4, 2, 2, 4, 2, 8 };//结合上面的代码 一个一个写
static int DivisionCircle[] = { 2, 6, 8, 4 };
static int Table[] = { 6, 6, 2, 6, 4, 4, 4, 8, 4, 6 };
public static int H(int X, int Y) {
int i;
for (i = 0; i < 4; i++) {
if (X == DivisionCircle[i]) {
break;
}
}
return DivisionCircle[(i + Y) % 4];//因为除数是循环 先找出i的位置 在向右移动Y位,每四位循环一次 所以%4
}
public static int funcation(int arr[], int len) {
int res = 1;
int k;
int carry;
int bit;
while (len > 1) {
k = arr[0];
carry = 0;
arr[len] = 0;
for (int i = 0; i <= len; i++) {
bit = arr[i]*2 + carry;
carry = bit / 10;
arr[i] = bit % 10;
}
for (int i = 1; i <= len; i++) {
arr[i - 1] = arr[i]; //可能有些人会想 arr[i-1]不为零 移位覆盖了 不影响吗 真的不影响 因为我们只要求 n/5 按照另外一篇推文里面介绍的递推公式(符合) 包括16/5 = 3 我们只要知道要除有几个2就好
}
if (arr[len] == 0) {//持续记录剩下的数的长度
len--;
}
res = res * H(Table[k],arr[0]+arr[1]*10)%10;//结合另外一篇递推公式
}
return res * FirstTen[arr[0]] % 10;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String n = sc.next();
if (n.length() < 2)
System.out.println(FirstTen[n.charAt(0) - '0']);
else {
int arr[] = new int[n.length() + 1];
for (int i = 0; i < n.length(); i++) {
arr[i] = n.charAt(n.length() - 1 - i) - '0';//逆序方便处理
}
System.out.println(funcation(arr, n.length()));
}
}
}
}