n!中有几个0等价于1~n中有min(因子2的个数,因子5的个数),因为因子2的个数必大于因子5的个数,ans为n/5+n/25+n/125…
将n转为5进制,假设n为1234,那么ans为(123+12+1|五进制)。此时要判断ans是否为偶数。
注意到如果一个数x为偶数进制,列如十进制,那么只要判断最后一个数是否是偶数即可,因为其他位的数都是乘以10的幂次,乘积皆为偶数,只有最后一位是乘以10的0次。
现在5进制为奇数进制,所有位的数都是乘以5的幂次(奇数),可以注意到1234这个数中2用了偶数次,1,3用了奇数次,那么所有用偶数次的数都不用去管,可以得到结论,只有奇数位的系数和为偶数时,5的个数为偶数个。
剩下的对这个5进制数数位DP即可。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define CLR(A, X) memset(A, X, sizeof(A))
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const double eps = 1e-10;
int dcmp(double x){if(fabs(x)<eps) return 0; return x<0?-1:1;}
const LL INF = 0x3f3f3f3f;
const LL MOD = 998244353;
const int N = 1e6+5;
int a[70];
LL dp[70][2];
LL dfs(int pos, int pre, bool flag) {
if(pos < 0) return pre==0?1:0;
if(flag && ~dp[pos][pre]) return dp[pos][pre];
int x = flag?4:a[pos];
LL ret = 0;
for(int i = 0; i <= x; i++) {
ret += dfs(pos-1, (pre+i*pos)%2, flag||i!=x);
}
if(flag) dp[pos][pre] = ret;
return ret;
}
void solve(LL n) {
int k = 0;
while(n) {
a[k++] = n%5;
n /= 5;
}
printf("%lld\n", dfs(k-1, 0, 0));
}
int main() {
CLR(dp, -1);
LL n;
while(~scanf("%lld", &n)) {
if(n == -1) break;
solve(n);
}
return 0;
}