Codeforces Round #529 (Div. 3) C. Powers Of Two题解及思路

 

       time limit per test 1 second memory limit per test 256 megabytes input

standard input output standard output Ivan wants to play a game with you. He picked some string ss of length nn consisting only of lowercase Latin letters.

 

        You don't know this string. Ivan has informed you about all its improper prefixes and suffixes (i.e. prefixes and suffixes of lengths from 11 to n−1n−1), but he didn't tell you which strings are prefixes and which are suffixes.

 

        Ivan wants you to guess which of the given 2n−22n−2 strings are prefixes of the given string and which are suffixes. It may be impossible to guess the string Ivan picked (since multiple strings may give the same set of suffixes and prefixes), but Ivan will accept your answer if there is at least one string that is consistent with it. Let the game begin!

Input

The first line of the input contains one integer number nn (2≤n≤1002≤n≤100) — the length of the guessed string ss.

The next 2n−22n−2 lines are contain prefixes and suffixes, one per line. Each of them is the string of length from 11 to n−1n−1 consisting only of lowercase Latin letters. They can be given in arbitrary order.

It is guaranteed that there are exactly 22 strings of each length from 11 to n−1n−1. It is also guaranteed that these strings are prefixes and suffixes of some existing string of length nn.

Output

Print one string of length 2n−22n−2 — the string consisting only of characters 'P' and 'S'. The number of characters 'P' should be equal to the number of characters 'S'. The ii-th character of this string should be 'P' if the ii-th of the input strings is the prefix and 'S' otherwise.

If there are several possible answers, you can print any.

 

来自 <https://codeforces.com/contest/1092/problem/C>

 

题意大概是给出两个数n和k,要求你将n分解为k个2的指数相加。

先给出我一开始的错误思路,这个思路是非常清晰且可行的,首先将n化为2进制数(记作num),很快可以发现,k 的取值范围在num中1的个数到n / 2之间——即YES或NO的判断条件,接下来的难题在于如何分解。我是利用贪婪,先找出num中1的位置,再分解

#include<algorithm>
#include <iostream>
#include  <sstream>
#include  <cstring>
#include  <cstdlib>
#include   <string>
#include   <vector>
#include   <cstdio>
#include   <math.h>
#include    <queue>
#include    <stack>
#include      <set>
typedef unsigned long long int ull;
#define rep(i,a,n) for (ull i = a; i < n; ++i)
#define per(i,a,n) for (ull i = n-1; i >= a; --i)
#define SZ(x) ((ull)x.size())
using namespace std;
//head
unsigned long long int update(ull n);
void tanlan(ull n, ull k);
ull ans[10000] = { 0 };
int main()
{
	ull n, k;
	ull num;
	ull flag = 0;
	ull div = 0, sum = 0, qqq = 1;
	cin >> n >> k;
	num = update(n);
	ull numi = num;
	do
	{
		if(numi % 10 == 1)
			div++;
		numi /= 10;
	}while (numi / 10 > 0);
	if ((n == (1 << div)) && k == 1) { cout << "YES" << endl; cout << n << endl;  return 0; }
	div++;
	numi = num;
	sum = n / 2;
	//cout << num << endl;
	//cout << div << "       " << sum << endl;
	if (k >= div && k <= sum)
	{
		cout << "YES" << endl;
		tanlan(num, k);
	}
	else
		cout << "NO" << endl;
	system("pause");
	return 0;
}
unsigned long long int update(ull n)
{
	unsigned long long int  result = 0, k = 1, i, temp;
	temp = n;
	while(temp){
		i = temp % 2;
		result = k * i + result;
		k = k * 10;
		temp = temp >> 1;
	}
	return result;
}
void tanlan(ull num, ull k)
{
	ull N = 0;
	ull div = 0;
	do
	{
		ull qqq = num % 10;
		if (qqq)
		{
			ans[N++] =( 1 << div);
		}
		num /= 10;
		div++;
	} while (num / 10 > 0);
	ans[N++] = 1 << div;
	div = 0;
	while (N < k)
	{
		while (ans[div] <= 2) div++;
		ans[div] = ans[div] >> 1;
		ans[N++] = ans[div];
	}
	sort(ans, ans + N);
	rep(i, 0, N) cout << ans[i] << " ";
	cout << endl;
}

但是这个思路不能AC的问题在于num,99999也就是10E5时num的值就达到了11000011010011111。而题目范围为10E9。所以必须想一个不需要num,直接通过n进行位操作的方法。

然后在探索新方法的道路上遇到了九九八十一难:

 

其中的坑大致上有一开始以为范围上限为n / 2,后来发现上限为n,并把分解的数不能为2改为不能为1,还有数组越界问题,不能开小也不能开大,AC的时候就像女神突然某天接受你的表白了一样!

贴上我的专属AC代码哈哈哈哈

#include<algorithm>
#include <iostream>
#include  <sstream>
#include  <cstring>
#include  <cstdlib>
#include   <string>
#include   <vector>
#include   <cstdio>
#include   <math.h>
#include    <queue>
#include    <stack>
#include      <set>
typedef long long ll;
#define rep(i,a,n) for (int i = a; i < n; ++i)
#define per(i,a,n) for (int i = n-1; i >= a; --i)
#define SZ(x) ((int)x.size())
using namespace std;
//head

#define maxn 1000009
ll a[maxn] = { 0 };
ll map(ll);
ll a_num = 0;
void tanlan(ll, ll, ll);
int main()
{
	ll n, k;
	cin >> n >> k;
	if (k == 1)
	{
		int qqq = 0;
		int N = n;
		while (N)
		{
			N = N >> 1;
			qqq++;
		}
		qqq--;
		if ((1 << qqq) == n) { cout << "YES" << endl; cout << n << endl; return 0; }
	}
	//if (k == n) { cout << "YES" << endl; while (k--) cout << "1 "; cout << endl; return 0; }
	if (k < map(n) || k > n) cout << "NO" << endl;
	else
	{
		cout << "YES" << endl;
		tanlan(n, k, map(n));
	}
	//system("pause");
	return 0;
}
ll map(ll n)
{
	ll vig = 0;
	ll num = 1;
	while (n)
	{
		if (n & 1 == 1) vig++;
		n = n >> 1;
	}
	return vig;
}
void tanlan(ll n, ll k, ll num)
{
	ll div = k - num;
	ll b = 0;
	while (n)
	{
		if (n & 1) a[a_num++] = 1 << b;
		b++;
		n = n >> 1;
		//cout << n << endl;
	}
	ll tag = 0;
	//cout << div << endl;
	while (div--)
	{
		ll c = a_num - 1;
		while (a[tag] == 1) tag++;
		a[tag] = a[tag] >> 1;
		a[a_num++] = a[tag];
	}
	sort(a, a + a_num);
	rep(i, 0, a_num)
		cout << a[i] << " ";
	cout << endl;
}

猜你喜欢

转载自blog.csdn.net/qq_42426141/article/details/85328971