1646C - Factorials and Powers of Two
1646C - Factorials and Powers of Two
题意:
给定一个数n 最大可到1e12 他可以用若干个 2x 和 xx!的和表示 其中x和xx是非负整数 求n可以用几个数表示的最小个数
思路:
对于数据 阶乘肯定不会超过14! 二进制数不会超过40 因为每个数都可以用若干个2的幂数相加得到。
所以直接枚举 每个阶乘数 选择取与不取 递归实现 过程中用min实时记录答案最小值
#include <bits/stdc++.h> #include <queue> #define ll unsigned long long #define pi acos(-1) #define FF ios::sync_with_stdio(false), cin.tie(0) using namespace std; const int mod = 1e9 + 7; const int maxn = 1e3 + 10; const int N = 2e5 + 10; const int inf = 0x3f3f3f3f; ll n, jc[16], ans; map<ll, ll>mp; //把一个数转化为二进制 获取这个二进制数中1的个数 int get_b(ll x){ int cnt = 0; while(x > 0){ //每次取出最后一位 if(x & 1) cnt++; x >>= 1; } return cnt; } //打表 void ff(){ jc[0] = jc[1] = 1; for(int i = 2; i <= 15; i++){ jc[i] = jc[i - 1] * i; } } //利用递归 void dfs(ll pos, ll fsum, ll num){ if(pos > 15) return; if(fsum > n) return; //每次更新答案 取最小值 ans = min(ans, get_b(n - fsum) + num); //取当前的指向的阶乘数 dfs(pos + 1, fsum + jc[pos], num + 1); //不取当前指向的阶乘数 dfs(pos + 1, fsum, num); } void solve(){ ans = inf; cin >> n; //从三开始因为1 2肯定是二进制更优 dfs(3, 0, 0); if(ans == inf) cout << "-1\n"; else cout << ans << "\n"; } int main() { FF; ff(); int t = 1; cin >> t; while(t --){ solve(); } return 0; }

浙公网安备 33010602011771号