Factorials and Powers of Two (CF2,C) (阶层->压状+二进制凑数 || 从推出的数据范瑞入手,采用暴力的做法)

 

 思路:

  • 遇到阶层,他是比2的腻方还要增长地特别快, 超过1e12 只需要 n=15
  • 而且他是要每一个数都是不同的, 因此可以 直接压状dp, 存 阶层可以组合出来的数
  • 然后利用二进制的特性,可以组合成任意的数, 来补一下没有组合出来的数字即可. 
  • 然后 t是很小的, 在枚举每一个组合出来的数, 只有3e4的大小, 来看哪一个的ans小.
#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define M 2000005 // 1e9

long long tmp;
long long val[M];
struct dian{
    long long val;
    int num;
}dp[M];
void init(){
    
    val[1]=1;
    for(ri i=2;i<=14;i++)
    {
        val[i]=val[i-1]*i;
    }
    for(ri i=1;i<=14;i++)
    {
        dp[(1<<(i-1))].val=val[i];
        dp[(1<<(i-1))].num=1;
    }
    for(ri i=1;i<(1<<14);i++)
    {
        for(ri j=1;j<=14;j++)
        {
            if(i&(1<<(j-1)))
            {
                dp[i].val=dp[i^(1<<(j-1))].val+val[j];
                dp[i].num=dp[i^(1<<(j-1))].num+1;
            }
        }
    }
    
}
long long n,m;
int T;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    init();
    cin>>T;
    while(T--)
    {
        cin>>n;
        int ans=1e9;
        for(ri i=0;i<(1<<14);i++)
        {
            int tmp=0;
            long long a=n;
            if(dp[i].val<=n)
            {
                a-=dp[i].val;
                tmp+=dp[i].num;
                while(a)
                {
                    if(a&1) tmp++;
                    a>>=1;
                }
                ans=min(ans,tmp);
            }
        }
        cout<<ans<<"\n";
    }
    
    return 0;
    
    
    
    
    
    
}
View Code

后记:

  • 遇到阶层他是增长地特别快的,常数特别特别小. 和压状,暴力联系在一起 

 

posted @ 2022-11-08 10:25  VxiaohuanV  阅读(22)  评论(0编辑  收藏  举报