题目
题意:输入一个n(0<=n<=10000),求 n! 的最低非零位的数字。如 5! = 120,得2。
分析:这种题好像以前见过好多次,(对,确实做过 = =,而且当年没做出来 = =!)。现在我是用记录每个质数有多少个来算的,把2跟5的去掉(2*5 = 10)。还要打表。n<=10000,872ms过的。
感觉应该有其他方法?
其他解法补在下面。
代码:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define bug(s) cout<<#s<<"="<<s #define MAXN 10002 int p[MAXN]; int a[MAXN]; void prime() { int n = MAXN; int idx = 0; memset(a, 0, sizeof(a)); for(int i=2; i<=n; i++) { if(!a[i]) { p[idx++] = i; for(int j=i*i; j<=n; j+=i) a[j] = 1; } } } int pn[MAXN]; //n!中相应质数的个数 int ans[MAXN]; // 打表 int main() { int n; prime(); ans[0] = 1; memset(pn, 0, sizeof(pn)); int maxj = 0; for(int i=1; i<=10000; i++) { int x = i; for(int j=0; p[j]<=i; j++) //每个质数 { if(!p[j]) break; //!! while(x%p[j] == 0) { x/=p[j]; pn[j]++; maxj = maxj>j? maxj: j; } } int cnt = pn[0]<pn[2]? pn[0]: pn[2]; //2 3 5 7... pn[0]-=cnt; pn[2]-=cnt; int ret = 1; for(int j=0; j<=maxj; j++) { for(int k=0; k<pn[j]; k++) //次数 { ret*=p[j]; ret%=10; } } ans[i] = ret; } while(cin>>n) { printf("%5d -> %d\n", n, ans[n]); } }
其他解法:
http://pageofcode.blogspot.com/2011/03/uva-568-just-facts.html(8ms......)/* 568 C "Just the Facts" */ /* @BEGIN_OF_SOURCE_CODE */ #include <stdio.h> #define FACT_UPTO 10001 int n, fact_lnzd[FACT_UPTO] ; void precompute(void) { int i, fact ; fact_lnzd[0] = fact_lnzd[1] = fact = 1 ; for (i=2; i<=FACT_UPTO; i++) { fact = fact * i ; while (fact%10==0) fact /= 10 ; fact = fact%100000 ; fact_lnzd[i] = fact%10 ; } } int main() { precompute() ; while (scanf("%d", &n) != EOF) printf("%5d -> %d\n", n, fact_lnzd[n]) ; return 0; }
以及 http://blog.csdn.net/alfredtofu/article/details/6299296 提到的两个。
一、
//f(i)=f(i-1)*i%10,i%5=0; //f(i)=mod(2,(n-1)%4+1))*f(n)%10,i%5!=0,n=i/5; //mod(2,(n-1)%4+1))的取值范围是2,4,6,8 #include <iostream> #include <cmath> #include <stdio.h> #include <string> using namespace std; //#define TEST long a[10001]={0, 1, 2, 6, 4, 2},b[5]={0, 2, 4, 8, 6}; int main() { #ifdef TEST freopen("input.txt", "r", stdin); #endif long m , n; for(long i = 6; i <= 10000; i++){ m = i % 5; n = i / 5; if(m != 0) a[i] = a[i - 1] * i % 10; else a[i] = b[(n - 1) % 4 + 1] * a[n] % 10; } while(cin >> n) { printf("%5d -> %d/n", n, a[n]); } return 0; }
二、
数论模板 = =!?
#include <iostream> #include <cmath> #include <stdio.h> #include <cstring> using namespace std; int lastdigit(char*buf) { 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 len=strlen(buf),a[110],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'; for(;len;len-=!a[len-1]) { 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; } return ret+ret%2*5; } int main() { char s[10]; while(cin >> s) { printf("%5s -> %d/n", s, lastdigit(s)); } return 0; }