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;
}