题意:
给n个节点,选择m条边,使得$\sum_{i=1}^{n}\sum_{j=1}^{n}dist(i,j)$最小。
思路:
肯定所有的点直接是根节点的子节点的时候是最优的。然后判断m和n的关系。
include "bits/stdc++.h"using namespace std;typedef long long LL;int main(int argc, char const *argv[]){ int T; LL n, m; scanf("%d",&T); while (T--) { scanf("%lld%lld", &n, &m); LL ans; if (m > n*(n - 1)/2) m = n*(n - 1)/2; if (m >= n - 1) ans = n*(n-1)+(n*(n-1)/2-m)*2; else ans = 2*m*m+(n-m-1)*(m+1)*2*n+(n-m-1)*(n-m-2)*n; printf("%lld\n", ans); } return 0;}
题意:
给出了n个元素和他们的和m,还有组成的$2^n$个子集和的统计,数组b从0-m,表示子集和是下标的有几个,然后反推出n个元素。
思路:
这道题我的锅。positive 没有注意到,然后一直考虑0的贡献。然后竟然一直蜜汁超时。。。。。。。。
看到题解,以为用背包进行优化,结果大家的代码都是直接计算新元素的贡献。。。。。。。。。
无奈。我的代码都优化废了,按照大家的意思重新写一遍。。。
#include "bits/stdc++.h"const int maxn = 15000;using namespace std;typedef long long LL;int b[maxn], a[maxn], dev[maxn];int ans[maxn];int main(int argc, char const *argv[]){ int T; scanf("%d", &T); while (T--) { int n, m; scanf("%d%d", &n, &m); memset(dev, 0, sizeof(dev)); for (int i = 0; i <= m; i++) scanf("%d", b+i); dev[0] = 1; int cnt = 0; for (int i = 1; i <= m; i++) { int res = b[i] - dev[i]; for (int j = 1; j <= res; j++) { a[cnt++] = i; //从后向前算贡献,否则计算后面的贡献的时候新贡献会影响 for (int k = m; k >= i; k--) { dev[k] += dev[k - i]; } } } printf("%d", a[0]); for (int i = 1; i < cnt; i++) { printf(" %d", a[i]); } printf("\n"); } return 0;}
题意:
有n个人参加比赛,他们的分值大于k的情况下分数高的人才会获胜,否则输赢是不定的。问最后有多少人可能赢
思路:
将n个人排序,第一次大于K之前的数的个数即为答案。
#include "bits/stdc++.h"using namespace std;int a[100010];int main(){ int T; scanf("%d",&T); while(T--) { int N, K; int ans = 1; scanf("%d%d",&N, &K); for(int i = 0; i < N; i++) scanf("%d", a+i); sort(a, a + N); for(int i = N - 1; i > 0; i--) { if((a[i] - a[i-1]) > K) break; ans++; } printf("%d\n",ans); } return 0;}