1646C - Factorials and Powers of Two

1646C - Factorials and Powers of Two

题意:

给定一个数n 最大可到1e12 他可以用若干个 2和 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; 
}

 

posted @ 2022-03-25 20:39  Yaqu  阅读(105)  评论(0)    收藏  举报