目录
题目
给定一个非负整数 n,请你判断是否存在一些整数 xi,能够使得 ,其中 t≥1,xi≥0,xi=xj iff i=j。
iff 表示当且仅当。
输入格式
输入包含多组测试数据。
每组数据占一行,包含一个非负整数 n。
最后一行是一个负数,表示输入结束,无需处理。
输出格式
每组数据输出一行结果,如果 n 能表示为若干数的阶乘之和,则输出 YES
,否则输出 NO
。
数据范围
0≤n≤1e7
每组输入最多包含 100组数据。
输入样例:
9
-1
输出样例:
YES
思路
xi=xj iff i=j 这个式子的意思就是,数组x[]中的数不能重复
题目输入的n最大为1e7,10!为3628800,9!为362880,所以只用考虑0到9的阶乘就好,
0到9的阶乘可以组成的数是有限个(二的十次方个)所以可以先用数组储存这可能组合出来的数
输入一个数就判断数组中有没有就好了。
为了方便的判断数组中有没有,使用哈希表储存所有的可能,再查找就会快。
代码
#include<algorithm>
#include<cstring>
#include<iostream>
#include<unordered_set>
using namespace std;
int f[10];//储存0到9的阶乘
unordered_set<int> S;//储存从f[]中选出来数相加可能出现的数,不重复
int main()
{
for(int i=0;i<10;i++)//求0到9的阶乘,储存到f[]中
{
f[i]=1;
for(int j=i;j;j--)//求阶乘,从大到小乘
{
f[i]*=j;
}
}
for(int i=1;i<1<<10;i++)//二进制枚举,最后算出来的总和储存到哈希表S中
{
int s=0;
for(int j=0;j<10;j++)
{
if(i>>j&1)//判断i的二进制表示中,从右向左数第j位是不是1
{
s+=f[j];//如果是1,就说明使用这个阶乘
}
}
S.insert(s);
}
int n;
while(cin>>n,n>=0)
{
if(S.count(n))
{
puts("YES");
}
else
{
puts("NO");
}
}
return 0;
}