Codeforces Round #774 (Div. 2)

Posted acwing_zyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #774 (Div. 2)相关的知识,希望对你有一定的参考价值。

思维,暴力dfs

比赛链接

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;

以上是关于Codeforces Round #774 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #774 (Div. 2)(ABCDE)

Codeforces Round #774 (Div. 2)题解

Codeforces Round #774 (Div. 2)题解

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)

Codeforces Round #726 (Div. 2) B. Bad Boy(贪心)