题目链接:
http://codeforces.com/gym/100796/problem/K
题意:
1e5次查询,每次输入一个正整数n。 1<=n<=1e18.
问n能不能拆成一些数字阶乘的乘积,能输出YES,不能输出NO
比如12能拆成 2!*3!输出YES
8能拆成2!*2!*2! 输出YES
5不能拆,输出NO
题解:
首先打一个阶乘的表,能够发现最大只能出现19的阶乘。那么暴力搜索1到19的阶乘 能够凑出的数字,放到set里,打完表
发现只有6284个合法的,然后每次查询就是看set里是否有这个数字,每次查询复杂度log 6284。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double inf=1e18;
ll fac[20];
set<ll> s;
void init(){
fac[0]=1;
for(int i=1;i<=19;i++) fac[i]=fac[i-1]*i;
}
void dfs(ll id,ll x){
s.insert(x);
if(id==20) return ;
ll y=1;
while(x<=inf/y){
dfs(id+1,x*y);
if(y<=inf/fac[id]) y*=fac[id];
else break;
}
}
int main(){
init();
dfs(2,1);
int t;
scanf("%d",&t);
while(t--){
ll x;
scanf("%lld",&x);
int flag=s.count(x);
if(flag) puts("YES");
else puts("NO");
}
return 0;
}