若干数阶乘的和

题目描述
给定一个非负整数 n,请你判断是否存在一些整数 xi,能够使得 n=∑1≤i≤txi!,其中 t≥1,xi≥0,xi=xj iff i=j。

iff 表示当且仅当。

输入格式
输入包含多组测试数据。

每组数据占一行,包含一个非负整数 n。

最后一行是一个负数,表示输入结束,无需处理。

输出格式
每组数据输出一行结果,如果 n 能表示为若干数的阶乘之和,则输出 YES,否则输出 NO。

数据范围
0≤n≤106,
每组输入最多包含 100 组数据。

样例
输入样例:
9
-1
输出样例:
YES

样例
输入样例:
9
-1
输出样例:
YES

思路一:
dfs暴力枚举
时间复杂度
参考文献
C++ 代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>
using namespace std;
const int N = 1e5+10;
int n;
int sum;
bool flag;
int a[10] = {1,1,2,6,24,120,720,5040,40320,362880};
void dfs(int sum,int u)
{
    if(u==10)
    {
        if(n==sum)flag=true;
        return ;
    }
    dfs(sum+a[u],u+1);
    dfs(sum,u+1);
}
int main()
{
    while(cin>>n,n>=0)
    {
        if(n==0)
        {
            cout << "NO"<<'\n';
            continue;
        }
        dfs(0,0);
        if(flag)puts("YES");
        else puts("NO");
        flag=false;
    }
    return 0;
}

Java代码

import java.util.*;

public class Main{
    static int[] p = new int[10];
    static int n;
    static boolean ans;
    public static void dfs(int u, int path){
        if(u == 10){
            if(path == n){
                ans = true;
            }
            return;
        }
        dfs(u + 1, path);
        dfs(u + 1, path + p[u]);
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        p[0] = 1;
        for(int i = 1; i <= 9; i ++){
            p[i] = p[i - 1] * i;
        }
        while(true){
            n = sc.nextInt();
            ans = false;
            if(n < 0){
                break;
            }
            dfs(0, 0);
            if(n == 0){
                ans = false;
            }
            if(ans){
                System.out.println("YES");
            }
            else{
                System.out.println("NO");
            }
        }
    }
}

思路二: 打表
时间复杂度
参考文献
C++ 代码

 

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>
using namespace std;
const int N = 1e5+10;
int n;
int a[N];
unordered_set<int>s;
int main()
{
    a[0]=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];
             s.insert(t);
        }
    }
    while(cin>>n,n>=0)
    {
        if(n==0)puts("NO");
        else if(s.count(n))puts("YES");
        else puts("NO");
    }
    return 0;
}

Java代码

import java.util.*;

public class Main{
    public static void main(String[] args){
        // 预处理阶乘
        int[] f = new int[10];
        f[0] = f[1] = 1;
        for(int i = 2; i <= 9; i++) f[i] = f[i-1] * i;

        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < 1 << 10; i++){
            int sum = 0;
            for(int j = 0; j < 10; j++){
                if(((i >> j) & 1) == 1){
                    sum += f[j];
                }
            }
            set.add(sum);
        }
        Scanner sc = new Scanner(System.in);
        while(true){
            int n = sc.nextInt();
            if(n < 0) break;
            if(n == 0) System.out.println("NO");
            else System.out.println(set.contains(n) ? "YES" : "NO");
        }

    }
}

GO代码

package main
import (
    "fmt"
)
var x int 
var nums [12]int
func main() {

    label : fmt.Scanf("%d", &x)
    m := make(map[int]bool)
    nums[0] = 1 
    for i:= 1;i < 12;i ++ {
        nums[i] = nums[i - 1] * i
    }
    for i:= 1 ; i< 1 << 10 ; i ++ {

        s:= 0 
        for j := 0 ; j < 10 ; j ++ {
            if i >> j & 1  == 1 {
                s += nums[j]
            }
        }
        if _, ok := m[s]; !ok {
            m[s] = true
        }
    }
    if x >= 0 {
        if _, ok := m[x]; ok {
            fmt.Println("YES")
        }else {
            fmt.Println("NO")
        }

        goto label
    }
}

欢迎留言点赞

嗷嗷嗷~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值