acwing.3481 阶乘的和 二进制枚举
题意描述
- 给你一个数n,问能否用几个数的阶乘的和组成n,每一个数的阶乘只能够用一次
思路:
把0~9的阶乘打表打出来,每一个只能选一次,这不就是01背包问题啊,每一个只能用一次,n就是最大背包容量,跟这一次选拔赛那个D题几乎一样既可以01背包、也可以二进制枚举。我真的服了,当时为啥不好好读题呢。回到这里,这个题同样也可以采用二进制枚举的方法,求出每一种情况的和,丢进哈希表里,然后查询n是否在哈希表中。
二进制枚举:
> 二进制的每一位都可以代表一种状态,选择或者不选择,那么每一个二进制数都代表一种情况。
二进制枚举代码:
#include <iostream>
#include <unordered_set>
using namespace std;
const int N=1e6+10;
int n;
int a[10];
unordered_set<int> hh;
int main()
{
a[0]=1;
a[1]=1;
for (int i=1;i<=9;i++) a[i]=a[i-1]*i;
for (int i=0;i<1<<10;i++)
{
int t=0;
for (int j=0;j<10;j++)
if (i>>j&1) t+=a[j];
hh.insert(t);
}
while (cin>>n)
{
if (n<0) break;
if (!n)
{
cout<<"NO"<<endl;
continue;
}
if (hh.count(n)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
01背包代码:
#include <iostream>
#include <unordered_set>
using namespace std;
const int N=1e6+10;
int n;
int a[10];
bool f[N];
int main()
{
a[0]=1;
a[1]=1;
for (int i=1;i<=9;i++) a[i]=a[i-1]*i;
int k=10;
f[0]=true;
for (int i=0;i<k;i++)
{
for (int j=N;j>=a[i];j--)
{
f[j]=f[j-a[i]]||f[j];
}
}
while (cin>>n)
{
if (n<0) break;
if (!n)
{
cout<<"NO"<<endl;
continue;
}
if (f[n]) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}杂题题解 文章被收录于专栏
看菜鸡做的水题
