hdu1066之数学题

以前好像做过一些,但是没有总结过,现在想重新的做一遍,好好的总结一下!

Problem Description
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 the factorial for N. 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, 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 containing the single last non-zero digit of N!.
 
Sample Input
1 2 26 125 3125 9999
 
Sample Output
1 2 4 8 2 8
题意就是求N的阶乘的最后一位非0的数字
自己先写了个o(n)的算法,(先统计2和5的个数,每次相乘只保留一位,最后再把多余的2补乘回去)结果是T了
在这里也贴一下
#include<iostream>
using namespace std;
int ju(int n)
{
 int m=0;
 while(n){
  m+=n/5;
  n=n/5;
 }
 return m;
}
int jua(int n)
{
 int m=0;
 while(n){
  m+=n/2;
  n=n/2;
 }
 return m;
}
int main()
{
 int n,a,b,i,j,sum;
  while(cin>>n){
   sum=1;
   a=ju(n);
  // cout<<a<<endl;
   b=jua(n);
  // cout<<b<<endl;
   for(i=1;i<=n;i++){
    if(i%2!=0&&i%5!=0){
     sum*=i;
     sum%=10;
     //cout<<sum<<endl;
    }
    else if(i%2==0&&i%5!=0&&i>2){
     j=i;
     while(j%2==0){
      j=j/2;
     }
     sum*=j;
     sum%=10;
       //cout<<sum<<endl;
    }
    else if(i%2!=0&&i%5==0&&i>5){
     j=i;
     while(j%5==0){
      j=j/5;
     }
     sum*=j;
     sum%=10;
      // cout<<sum<<endl;
    }
    else if(i%10==0){
     j=i;
     while(j%10==0){
      j=j/10;
     }
     while(j%2==0){
      j=j/2;
     }
     while(j%5==0){
      j=j/5;
     }
     sum*=j;
     sum%=10;
       //cout<<sum<<endl;
    }
   }
   for(i=1;i<=(b-a);i++){
    sum*=2;
    sum%=10;
   }
   cout<<sum<<endl;
  }
  return 0;
}
然后果断去了大神们的博客看看了新的方法,结果第一句话就是如果用上面的方法会T
 还要优化,优化,再优化
解析是n(logn)的复杂度
n却是数字的长度,可见这个N是肥肠飞常大的
看了20分钟,完全不理解,暂时把吉林大学的模板放在这里,慢慢再去理解
#include<stdio.h>   
#include<string.h>    
#define maxn 10001   
const int mod[20]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};    
int lastdigit(char buf[])   
{   
    int len=strlen(buf),a[maxn],i,c,ret=1;   
    if(len==1)return mod[buf[0]-'0'];   
    for(i=0;i<len;i++)   
        a[i]=buf[len-1-i]-'0';   
    while(len)   
    {   
        ret=ret*mod[a[1]%2*10+a[0]]%5;  // % 优先级比 * 高 
        for(c=0,i=len-1;i>=0;i--)   
        {   
            c=c*10+a[i],a[i]=c/5,c%=5;   
        }   
        len-=!a[len-1];   
    }   
    return ret+ret%2*5;   
}     
int main()   
{   
    char  n[maxn];   
    while(scanf("%s",n)!=EOF)   
    {   
        printf("%d ",lastdigit(n));   
    }   
    return 0;   
}   
 
原文地址:https://www.cnblogs.com/ACWQYYY/p/4487997.html