广东工业大学文远知行杯新生程序设计竞赛(重现赛)
1,F,亚子和燐子的game
思路:
我们可以维护一个堆(里面的数都相等,其实就是一个数),每扔进去一个数,就继续维持堆中数字相等(维持方法,就是谁大谁除3),如果发现维护不了,那么就是无法实现
#include <bits/stdc++.h>
using namespace std;
#define ll long long
typedef unsigned long long ull;
typedef pair<long long, long long> pll;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 100;
int main()
{
ll n, a, b, cnt = 0;
cin >> n >> a;//把第一个数作为堆的起点
bool flag = 1;
for (int i = 1; i < n; ++i)
{
cin >> b;//后面输入n-1个数
if (flag)
{
while (a != b)//尝试让a与b相等
{
if (a > b)a /= 3, cnt += i;//对a堆操作(里面有i个数),所以操作一次,次数加i
if (a < b)b /= 3, cnt++;//对一个数b操作,加一次就好
if (a == b)break;//相等跳出
if (a < 3 && b < 3) //如果都小于3还没有相等跳出,说明无法维护
{
flag = 0;
break;
}
}
}
}
if (flag)cout << cnt << endl;
else cout << "Lose" << endl;
return 0;
}
2,J,狐臭的等比数列
思路:
我们把原始a数组升序排列。会发现a[i+1]/a[i]就是公比的次幂q^k,所以我们讨论最少几个,其实就是讨论相邻的q^k(共n-1个)的k大于1的有几个,有就是加上k-1,所以我们建一个数组来存q^k,但是我们发现,q可以是分数。
我们又会发现,就算q是分数,也被a[0]*q^n的a[0]消去,所以我们可以不用管分母,提取分子即可
具体操作如下
3 ,k,玩石头a
思路:
求石头堆的最大魅力值可以看成在i魅力下最小石头重量m[i](限制条件,每次放入石头重量x,必须比当前魅力值允许的小),其实你会发现就是个背包--看起来不知道魅力值范围会被t(bushi)
我们发现是有可行性的,ai<1e9,我们清楚最小数列是斐波那契数列,自己打表发现第35个值超过1e9,所以其实最多35个石头叠一起,魅力值最大100,所以最大魅力值绝对不超过3600。
我们可以按重量排序后,把魅力值当作背包容量,限制条件是m[i]在i魅力值情况下最小重量是m[i],当m[i]小于当前石头x时,得到递推式 m[i + y] = min(m[i + y], x + m[i]);从而得到每个魅力值的最小重量
#include <bits/stdc++.h>
using namespace std;
#define ll long long
typedef unsigned long long ull;
typedef pair<long long, long long> pll;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 100;
const int M = 3600;
ll m[M + 200];//压空间,但一定注意稍微大一些,这样保证不会越界
int main()
{
vector<pll>v;
int n;
cin >> n;
int x, y;
for (int i = 1; i <= n; ++i)
{
cin >> x >> y;
v.push_back({x, y});
}
sort(v.begin(), v.end());//排序,是为了从小重量递推回去大重量
memset(m, 0x3f, sizeof(m));//初始化任意魅力值石头重量inf
m[0] = 0;//当然,魅力值0,重量0
ll maxn = -INF;
for (auto [x, y] : v)
{
for (int i = M; i >= 0; i--)//从大到小,防止后效性
{
if (m[i] < x)//限制条件,每次放入石头,必须比原来的大(m[i]装的是当前一个堆的石头重量,放入x是垫最下面的
{
m[i + y] = min(m[i + y], x + m[i]);//能放,我们就可以求出魅力值加y后石头堆的最小重量
maxn = max(maxn, i + y);//只要有出现的魅力值,就是能够堆出来的石头堆
}
}
}
cout << maxn << endl;
return 0;
}