Codeforces Round #774 (Div. 2)

比赛链接

Codeforces Round #774 (Div. 2)

C. Factorials and Powers of Two

A number is called powerful if it is a power of two or a factorial. In other words, the number \(m\) is powerful if there exists a non-negative integer \(d\) such that \(m=2^{d}\) or \(m=d !\), where \(d !=1 \cdot 2 \cdot \ldots \cdot d\) (in particular, 0 ! \(=1\) ). For example 1,4 , and 6 are powerful numbers, because \(1=1 !, 4=2^{2}\), and \(6=3 !\) but 7,10 , or 18 are not.

You are given a positive integer \(n\). Find the minimum number \(k\) such that \(n\) can be represented as the sum of \(k\) distinct powerful numbers, or say that there is no such \(k\).

Input

Each test contains multiple test cases. The first line contains the number of test cases \(t(1 \leq t \leq 100)\). Description of the test cases follows.
A test case consists of only one line, containing one integer \(n\left(1 \leq n \leq 10^{12}\right)\)

Output

For each test case print the answer on a separate line.
If \(n\) can not be represented as the sum of distinct powerful numbers, print \(-1\).
Otherwise, print a single positive integer - the minimum possible value of \(k\).

Example

input

4
7
11
240
17179869184

output

2
3
4
1

Note

In the first test case, 7 can be represented as \(7=1+6\), where 1 and 6 are powerful numbers. Because 7 is not a powerful number, we know that the minimum possible value of \(k\) in this case is \(k=2\).
In the second test case, a possible way to represent 11 as the sum of three powerful numbers is \(11=1+4+6\). We can show that there is no way to represent 11 as the sum of two or less powerful numbers.

In the third test case, 240 can be represented as \(240=24+32+64+120\). Observe that \(240=120+120\) is not a valid representation, because the powerful numbers have to be distinct.

In the fourth test case, \(17179869184=2^{34}\), so 17179869184 is a powerful number and the minimum \(k\) in this case is \(k=1\).

解题思路

思维,dfs

可以发现不可能出现无解的情况(由二进制表示,一个数总是可以表示为若干个不相同的二次幂相加的形式),可以将所有小于等于 \(1e12\) 的乘方表示出来,共有 \(16383\) 个数,然后每次暴力每次选择某一个乘方数或不选,最后再用若干个二次幂来表示剩余的数,注意当乘方数中包含 \(1\)\(2\) 时,剩余的数的二次幂不能出现 \(1\)\(2\),否则两个数会重复

  • 时间复杂度:\(O(16383\times T)\)

代码

// Problem: C. Factorials and Powers of Two
// Contest: Codeforces - Codeforces Round #774 (Div. 2)
// URL: https://codeforces.com/contest/1646/problem/C
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}


int t,tot;
LL n,a[60];
vector<int> chosen;
unordered_map<LL,int> f;
unordered_set<LL> s1,s2;
void dfs(int x)
{
	if(x==tot+1)
	{
		LL t=0;
		bool fl[2]={0};
		for(int i:chosen)
		{
			if(a[i]==1)fl[0]=1;
			if(a[i]==2)fl[1]=1;
			t+=a[i];
		}
		if(t>1e12||t==0)return ;
		if(fl[0])s1.insert(t);
		if(fl[1])s2.insert(t);
		f[t]=chosen.size();
		return ;
	}
	chosen.pb(x);
	dfs(x+1);
	chosen.pop_back();
	dfs(x+1);
}
int main()
{
    LL b=1;
    for(int i=1;;i++)
    {
    	b*=i;
    	if(b>1e12)break;
    	a[++tot]=b;
    }
    dfs(1);
    for(cin>>t;t;t--)
    {
    	cin>>n;
    	int res=__builtin_popcountll(n);
    	for(auto t:f)
    	{
    		LL x=t.fi;
    		int y=t.se;
    		if(x>n)continue;
    		LL z=n-x;
    		if(s1.count(x)&&(z&1))continue;
    		if(s2.count(x)&&(z>>1&1))continue;
    		res=min(res,y+__builtin_popcountll(z));
    	}
    	cout<<res<<'\n';
    }
    return 0;
}
posted @ 2022-03-24 09:49  zyy2001  阅读(75)  评论(0编辑  收藏  举报