zzuliOJ 1089: 阶乘的最高位

传送门

思路:考虑只保留最高位,然后对最高位操作即可。用 d o u b l e double double时注意结果要化为 i n t int int,而不是 % . 0 f \%.0f %.0f,因为这不是向下取整。

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int main(){
	int n;
	cin>>n;
	double x=1.0;
	for(int i=1;i<=n;i++){
		 x*=i;
		 while(x>=10) x/=10;
	}
	printf("%d\n",(int)x);
	return 0;
}

方法2: 取对数。

a . b c d × 1 0 k = n ! a.bcd\times 10^k=n! a.bcd×10k=n!两边取对数。

l o g 10 ( a . b c d ) = l o g 10 n ! − k log_{10}(a.bcd)=log_{10}n!-k log10(a.bcd)=log10n!k

l o g 10 n ! = l o g 10 1 + l o g 10 2 ⋯ + l o g 10 n log_{10}n!=log_{10}1+log_{10}2\dots+log_{10}n log10n!=log101+log102+log10n

k = ( i n t ) l o g 10 n ! k=(int)log_{10}n! k=(int)log10n!

可以用 d o u b l e double double表示 n ! n! n!

所以可以一边遍历一遍计算。最后 ( i n t ) p o w ( 10 , x ) (int)pow(10,x) (int)pow(10,x)即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int main(){
	int n;
	cin>>n;
	double x=0.0;
	for(int i=1;i<=n;i++){
		x+=log10(i);
		x-=(int)x;
	}
	printf("%d\n",(int)pow(10,x));
	return 0;
}