每天一道 CodeForces 构造/思维题 难度1500 (day3)

简介: 每天一道 CodeForces 构造/思维题 难度1500 (day3)

1题目

题目链接 Factorials and Powers of Two

题目大意:

给你一个整数n(1<=n<=1e12),它可以由两种类型的数组成

  • 类型1:2的整数次幂
  • 类型2:k的阶乘

这个数可以由这两种类型任意多个组成,但是组成n的数字中不能由相同数字。

问最少由多少个这两种类型的数组成整数n

2思路

这是一个整数划分问题,但是这个整数特别大,所以不能用动态规划来求。

我们可以假设只有类型1组成整数n,那么只需要n的2进制有多少个1就是答案了。

但是我们现在是两种类型的结合

假设有k个数的阶乘和为sum之后,那么就剩下n-sum了,剩下全部由类型1组成。

所以 n = k + n-k ,cnt = k + get_bit_count(n-sum)

所以为了使cnt最小,我们只需要计算所有k的可能性即可,这里k最多有14,因为15!> 1e12 了。所以我们可以用位运算来枚举所有的集合,而且集合中每个数字都不一样,还有n-sum中的所有数也不会一样。

注意这里使没办法贪心的,没有规律可言,所以只能按照枚举所以的情况即可。

3代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> PII;
#define x first
#define y second
const int N = 2e4 + 10;
PII a[N];
ll f[20];
int get_bit(ll x)
{
    int ans = 0;
    for (int i = 0; i < 60; i++)
    {
        if (x >> i & 1)
            ans++;
    }
    return ans;
}
void init()
{
    f[0] = 1;
    for (int i = 1; i <= 14; i++)
        f[i] = f[i - 1] * i;
    for (int i = 0; i < 1 << 14; i++)
    {
        ll ans = 0;
        int cnt = 0;
        for (int j = 0; j < 14; j++)
        {
            if (i >> j & 1)
            {
                ans += f[j + 1];
                cnt++;
            }
        }
        a[i] = {ans, cnt};
    }
}
void solve()
{
    ll n;
    cin >> n;
    int ans = 1e9;
    for (int i = 0; i < 1 << 14; i++)
    {
        if (a[i].x <= n)
        {
            ans = min(ans, a[i].y + get_bit(n - a[i].x));
        }
    }
    cout << ans << endl;
    return;
}
signed main()
{
    // freopen("in.in", "r", stdin);
    // freopen("out.out", "w", stdout);
    init();
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}
相关文章
|
4月前
|
存储 算法 Python
Python算法界的秘密武器:分治法巧解难题,贪心算法快速决策,动态规划优化未来!
【7月更文挑战第9天】Python中的分治、贪心和动态规划是三大关键算法。分治法将大问题分解为小问题求解,如归并排序;贪心算法每步选局部最优解,不保证全局最优,如找零钱;动态规划存储子问题解求全局最优,如斐波那契数列。选择合适算法能提升编程效率。
68 1
|
4月前
|
存储 算法 Python
震撼!Python算法设计与分析,分治法、贪心、动态规划...这些经典算法如何改变你的编程世界!
【7月更文挑战第9天】在Python的算法天地,分治、贪心、动态规划三巨头揭示了解题的智慧。分治如归并排序,将大问题拆解为小部分解决;贪心算法以局部最优求全局,如Prim的最小生成树;动态规划通过存储子问题解避免重复计算,如斐波那契数列。掌握这些,将重塑你的编程思维,点亮技术之路。
75 1
|
5月前
|
算法 JavaScript 程序员
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
34 0
|
6月前
|
算法
枚举算法:解决问题的穷举之道(二)
枚举算法:解决问题的穷举之道(二)
|
6月前
|
算法
枚举算法:解决问题的穷举之道(一)
枚举算法:解决问题的穷举之道(一)
算法思维之穷举法
算法思维之穷举法
|
6月前
|
机器学习/深度学习 算法 Java
「程序员必须掌握的算法」动态规划「中篇」
「程序员必须掌握的算法」动态规划「中篇」
剑指offer_发散思维---求1+2+3+...+n
剑指offer_发散思维---求1+2+3+...+n
55 0
算法竞赛之查找算法(持续补充...)
算法竞赛之查找算法(持续补充...)
下一篇
无影云桌面