C. Factorials and Powers of Two(最详细二进制枚举、爆搜)

一、题目

C. Factorials and Powers of Twohttps://codeforces.com/contest/1646/problem/C

二、题目大意及其分析

1、题目意思:一个数能否由一些  2的次方 或者 n的阶乘 等数组成(并且这些数要不一样的),求最小的数量。(例如:7=6(来自于3!)+1(来自于0!或者1!或者 2的0次方) )

2、一个数字肯定是可以由二进制表示出来的,所以我们可以先枚举所有阶乘可以组成的数,再用剩下的数用二进制表示(如27=4!+3),所以可以有(27=4!+2+1),答案就是3;

3、枚举阶乘可以组成数,可以爆搜,也可以用二进制枚举;具体可以看代码,不懂得可以下面评论。

三、爆搜枚举阶乘可以组成数 的代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
ll t = 1,x,ans,f[20];

ll count(ll x){ll res = 0; while (x) res += x & 1,x >>= 1; return res;}
//爆搜去寻找那个男人
void dfs(ll pos,ll sum,ll ant){
	if (sum > x) return;
	if (pos == 15){
		ans = min(ans,ant + count(x - sum));
		return;
	}
    //不需要这个f[i]值的,继续往下搜索
	dfs(pos + 1,sum,ant);
    //需要f[i]的,然后继续往下搜索
	dfs(pos + 1,sum + f[pos],ant + 1);
}
int main()
{
    cin >> t;
    f[0] = 1;
    for (ll i = 1;i <= 14;i += 1) f[i] = f[i - 1] * i;
    
    while (t --){
	    cin>>x; ans = 1e18;
	    dfs(0,0,0);
	    cout<<ans<<endl;
    }
	return 0;
}

四、二进制枚举阶乘可以组成数 的代码

#include<iostream>
#include<vector>
#include<algorithm>
#define LL long long
using namespace std;

vector<LL> factBook;
//预处理出1到14的阶乘,可知15的阶乘一定是大于n的
void preprocess()
{
    LL curFact = 1;
    for(int i = 0; i < 15; i++)
    {
        curFact *= max(1,i);
        if(i > 2 || i == 0) factBook.push_back(curFact);
    }
}

//计算出一个数中用二进制表示的位数
int getOneCount(LL n)
{
    int cnt = 0;
    while(n > 0)
    {
        cnt++;
        n -= (n & -n);
    }
    return cnt;
}

//开始对阶乘可能组成的数的枚举
int getPowerCount(LL n)
{
    
    const int M = factBook.size();
    
    //求最大的可能枚举的数量
    const int maxMask = (1 << M);
    int best = 99;

    //然后进行每个数的枚举行动
    for(int mask = 0; mask < maxMask; mask++)
    {
        int penalty = 0;
        LL remain = n;
        for(int i = 0; i < M; i++)
        {
            if((mask>>i) &1 )
            {
                remain -= factBook[i];
                penalty++;
            }
        }
        if(remain < 0) continue;
        penalty += getOneCount(remain);

        best = min(best, penalty);
    }
    if(best >= 99) return -1;
    return best;
}

int main()
{
    preprocess();
    int tc; scanf("%d",&tc);
    for(int test_id = 1; test_id <= tc; test_id++)
    {
        LL n; scanf("%lld",&n);
        const int ans = getPowerCount(n);
        printf("%d\n", ans);
    }
    return 0;
}


五、总结

        做题要多想想

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值