USACO 阶乘
原创
©著作权归作者所有:来自51CTO博客作者Nemaleswang的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目链接:阶乘
这个oj是我们学校自己的oj,USACO实在是太不好找题目做了,所以爬了一些题目到我们自己的oj上写题。这道题目的题意实际很简单的,求k的阶乘最后一位的非零的数字,这道题目跟hdoj 1066(poj 1150)是类似的,不过hdoj 1066(poj 1150)数据更强,用下面的代码会超时,所以会采用找循环节的方法,具体见博客hdoj 1066(poj 1150)的解法,这里只给出最好理解的代码。
因为是要找非零位,那么我们可以知道怎样才会出现零呢?只有2和5可以去凑零,为什么4和5不可以(因为4还可以拆两个2啊),所以我们只需要找2和5出现的个数,当然2的数量远远多于5的个数,仔细想一想就知道了,所以min(sum5,sum2)全部都可以删掉了,只留下sum2-sum5个2,和剩下的数字(不能被2整除也不能被5整除),两者相乘就可以了,具体看代码
#include <bits/stdc++.h>
using namespace std;
int n,sum1,sum2;
int cal(int x){
while(x%2 == 0){
sum1++;
x/=2;
}
while(x%5 == 0){
sum2++;
x/=5;
}
return x;
}
int quick_pow(int a,int b){
int ans = 1;
while(b){
if(b&1) ans = (ans*a)%10;
a = (a*a)%10;
b>>=1;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
while(~scanf("%d",&n)){
sum1 = sum2 = 0;
int p = 1;
for(int i = 1;i <= n;i++)
p *= cal(i),p %=10;
int ans = (quick_pow(2,sum1-sum2)*p)%10;
printf("%d\n",ans);
}
return 0;
}