题意从尾部找第一个非0的数 这样就可以考虑下怎样会形成0 这个都知道 只有因子2和因子5相遇会形成0 那这样可以先把所有的2和5先抽出来,这样就保证了其它的数相乘就不会再出现0了 这样就可以转换成尾数相乘的结果 当然可能2的个数会剩余 这一部分留到最后去算
step1 抽出所有的5和2 n!里因子x的个数 求法: n/x+gn(n/x);
这样结果就为1 3 7 9 之一 这样就需要求一下尾部3,,7,9的出现的次数,并且可以发现它们都是以4为周期的 包括2
step2 尾部3 7 9出现的次数 f[n] + find(n/2) 因为抽走了2 x出现的次数g[n][x] = n/10+(n%10>=x)+ggn(n/5)因为抽走了5
最后再把2的影响补上
题意求N!/(n-m)! 因为N!包含(n-m)! 故可以通过各个数出现的次数相减求得最后的结果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int o[10][2]; 18 int p[10][6]; 19 int gn(int n,int x) 20 { 21 if(n==0) 22 return 0; 23 return n/10+(n%10>=x)+gn(n/5,x); 24 } 25 int ggn(int n,int x) 26 { 27 if(n==0) 28 return 0; 29 return gn(n,x)+ggn(n/2,x); 30 } 31 int find0(int n,int x) 32 { 33 if(n==0) return 0; 34 return n/x+find0(n/x,x); 35 } 36 int main() 37 { 38 int n,m; 39 p[3][1] = 3,p[3][2] = 9,p[3][3] = 7,p[3][0] = 1; 40 p[7][1] = 7,p[7][2] = 9,p[7][3] = 3,p[7][0] = 1; 41 p[9][1] = 9,p[9][2] = 1,p[9][3] = 9,p[9][0] = 1; 42 p[2][1] = 2,p[2][2] = 4,p[2][3] = 8,p[2][0] = 6; 43 while(cin>>n>>m) 44 { 45 memset(o,0,sizeof(o)); 46 m = n-m; 47 o[5][0] = find0(n,5); 48 o[5][1] = find0(m,5); 49 o[2][0] = find0(n,2); 50 o[2][1] = find0(m,2); 51 52 o[3][0] = ggn(n,3); 53 o[7][0] = ggn(n,7); 54 o[9][0] = ggn(n,9); 55 o[3][1] = ggn(m,3); 56 o[7][1] = ggn(m,7); 57 o[9][1] = ggn(m,9); 58 o[5][0] -= o[5][1]; 59 o[2][0] -= o[2][1]; 60 int a = o[3][0]-o[3][1]; 61 int b = o[7][0]-o[7][1]; 62 int c = o[9][0]-o[9][1]; 63 int k = o[2][0]-o[5][0]; 64 int ans = 1; 65 if(a) ans*=p[3][a%4]; 66 if(b) ans*= p[7][b%4]; 67 if(c) ans*= p[9][c%4]; 68 if(k) ans*= p[2][k%4]; 69 cout<<ans%10<<endl; 70 } 71 return 0; 72 }