不是萌新,问一下思路是否有问题
查看原帖
不是萌新,问一下思路是否有问题
519384
Link_Cut_Y楼主2022/10/29 17:02

首先对玉枝进行排序。枚举最大值 ii ,从 i1i - 1 开始枚举次大值 jj ,枚举第三大值 kk。可以发现,kk 是单调递增的。这样,如果确定了一个最小的大于 wiwjw_i - w_j 的玉枝 kk,那么当前的贡献就是 (i=1jkCjki×i)×wi(\sum_{i = 1}^{j - k} C_{j - k}^{i} \times i) \times w_i

最后累加总和就可以了。复杂度 O(n2)O(n ^ 2) 。但是每个子任务都没几个对的。求大佬解惑。

Code\large \mathfrak{Code}

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

#define int long long

using namespace std;

using LL = long long;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
const int mod = 20060723;
const int N = 5010;

int n;
int c[N][N], s[N];
int w[N];

void init() {
	for (int i = 0; i <= n; i ++ )
        for (int j = 0; j <= i; j ++ )
            if (!j) c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
	
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= i; j ++ )
			c[i][j] = c[i][j] * (j + 2) % mod;
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= i; j ++ )
			s[i] = (s[i] + c[i][j]) % mod;
}

LL solve() {
	LL ans = 0;
	for (int i = 3; i <= n; i ++ ) { // ö¾Ù×î´óÖµ
		int k = 1; // µÚÈý´óÖµ£¬µ¥µ÷µÝÔö 
		for (int j = i - 1; w[j] > (w[i] >> 1); j -- ) { // ö¾Ù´Î´óÖµ
			while (w[k] + w[j] <= w[i]) k ++ ;
			if (k >= j) break;
			ans = (ans + s[j - k] * w[i] % mod) % mod;
		}
	}
	return ans;
}

signed main() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; i ++ ) {
		scanf("%lld", &w[i]);
	}
	
	sort(w + 1, w + n + 1);
	init();
	printf("%lld\n", solve());
	
	return 0;
}
2022/10/29 17:02
加载中...