东北林业大学6.21训练补题

由于严重划水,大部分题解几乎是共享抄袭*goliter *的成果
在此只补两道

阿祥和阿华

在这里插入图片描述

分析 :

看了Go利特(goliter)的题解,要用约数定理,嗯?不会!
在这里插入图片描述在这里插入图片描述

约数个数 :

** 排列组合,对于每个Pi都可选0到ai来合成一个约数,所以个数就是把所有可能乘起来**

约数之和 :

展开就是所有的约数,这个式子包含了所有约数的可能性

如何转换题意 (参考GO利特):

在这里插入图片描述
GO利特说得对

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
	int t;
	cin >> t;
	while (t--) {
		ll ans = 1;
		ll n;
		cin >> n;
		for (int i = 2; i * i <= n; i++) {
			int cnt = 0; //
			if (n % i == 0) {
				while (n % i == 0) {
					cnt++;
					n /= i;
				}
				ans *= (cnt * 2 + 1); //约数个数定理
			}
		}

		if (n > 1)
			ans *= 3; // 把最后一个约数,也就是他本身乘上  (1*2+1)
		cout << (ans + 1) / 2 << endl;
	}
}

搭积木

在这里插入图片描述

分析:

再来借鉴(copy)一下实验室顶尖战力的题意分析
在这里插入图片描述
先对a升序排序,如此操作,对于每一个Bi,合理的木只会出现在i前面
分析到这里,直接开始狂喜——记忆化搜索O(n)拿下
注意细节问题 : 要对边长进行swap操作 举个例子 (5,1)和(3,5),自行模拟一下前后结果

#include <bits/stdc++.h>
using namespace std;

const int N = 1e3 + 10;
typedef long long LL;


struct node {
	LL a, b, c, d;
};
node blocks[N];
LL n;

bool cmp(node g, node h) {
	if (g.a == h.a) {
		if (g.b == h.b) {
			return g.d > h.d;
		} else
			return g.b < h.b;
	} else
		return g.a < h.a;
}
LL res;
LL f[N];
LL b[N];

LL dfs(LL x) {

	if (f[x])
		return b[x];
	f[x] += blocks[x].c;
	res = max(res, f[x]);
	for (LL i = x - 1; i >= 1; i--) {
		LL now = f[x];
		if (blocks[x].d == 0) {
			if (blocks[x].a >= blocks[i].a && blocks[x].b >= blocks[i].b) {
				b[x] = max(b[x], f[x] + dfs(i));

				res = max(res, b[x]);
			} else
				continue;
		}
		if (blocks[x].d == 1) {
			if (blocks[x].a == blocks[i].a && blocks[x].b > blocks[i].b || blocks[x].a != blocks[i].a
			        && blocks[x].b >= blocks[i].b) {
				b[x] = max(b[x], f[x] + dfs(i));
				res = max(res, b[x]);
			} else
				continue;
		}
		if (blocks[x].d == 2) {
			if (blocks[x].a > blocks[i].a && blocks[x].b > blocks[i].b) {
				b[x] = max(b[x], f[x] + dfs(i));
				res = max(res, b[x]);
			} else
				continue;
		}

	}
	b[x] = max(b[x], f[x]);
	return b[x];
}

int main() {
	while (scanf("%lld", &n) != -1) {
		memset(b, 0, sizeof(b));
		for (LL i = 1; i <= n; i++) {
			scanf("%lld%lld%lld%lld", &blocks[i].a, &blocks[i].b, &blocks[i].c, &blocks[i].d);
			if (blocks[i].a < blocks[i].b)
				swap(blocks[i].a, blocks[i].b);
		}
		
		sort(blocks + 1, blocks + n + 1, cmp);
		memset(f, 0, sizeof(f));
		res = 0;
		
		for (LL i = n; i >= 1; i--) {
			dfs(i);
		}
		cout << res << endl;
	}
    return 0;
}
  • 18
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值