2017 Multi-University Training Contest

来源:互联网 发布:oracle sql 双引号 编辑:程序博客网 时间:2024/06/05 13:25

日常读错题,赛后一个钟还是不懂为何是签到题。
为什么你们都能过签到题啊。
为什么120名以后都只能过签到题啊orz
hdu 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095

Rikka with Candies

题意:
有n个小朋友,有m种糖果,每个小朋友有ai的钱可以去买糖果,糖果价钱为bj
一个人他只会疯狂的买一种糖果,买到没钱为止。
现在有q次询问,问小朋友可能买剩下那么多钱的情况数有多少。答案%2

思路:
大神们都说%2就会想到位压缩。。
其实想要求的就是Ai%Bi=k
我们把公式转换一下就是要求 (Aik)%Bi=0的情况数
我们可以枚举k。且当枚举到k的时候必须满足。Bi>kAi>k
我们可以将所有的AiBi都用bitset压缩一下。
每次a>>k相当于A数组里所有数都-k,去除掉小于0的。
剩下的那些跟已有的Bi的因子且运算一下。就是当模的答案为k时(Aik)%Bi=0的情况数。
具体可以看代码。
强行卡在3496ms过了。。
听说bitset没有区间操作。大神们都手写bitset

#include <bits/stdc++.h>#define MAXN 50005using namespace std;bitset<MAXN> a, b, fac, ans;void init() {    a.reset();    b.reset();    fac.reset();    ans.reset();}void work(int mx) {    for (int i = mx; i >= 0; i--) {        ans[i] = ((a >> i) & fac).count() & 1;        if (b[i]) {            for (int j = 0; j < MAXN; j += i) {                fac.flip(j);            }        }    }}int main() {    int T, n, m, q, t;    scanf("%d", &T);    while (T--) {        init();        scanf("%d %d %d", &n, &m, &q);        int mx = 0;        while (n--) {            scanf("%d", &t);            a.set(t);        }        while (m--) {            scanf("%d", &t);            b.set(t);            mx = max(t, mx);        }        work(mx);        while (q--) {            scanf("%d", &t);            puts(ans[t] ? "1" : "0");        }    }    }

Rikka with Graph

题意:
给n个点m条边,两两点的距离是1,如果两点之间没有直接连通的点的话,那他们距离为n。

orz读错题wa了5发。以为他说的是。两两点之间的距离为两两点的点数。然后队友说样例跑不过啊。然后就。。所有相连的点距离都是2,不连的点距离是n。。然后不算重边。样例竟然神奇的跑过了。于是wa了一个钟

该图最优情况肯定是,一点为中心,其他点都跟这个点连线。
若m < n - 1 则肯定有点在外面。直接计算距离即可。
反之。当中心点与所有点都相连的时候,中心点与所有点距离都为1,其他两两点之间距离都为2,然后每次给两两点加边。他们距离-1。直接推公式可得

#include <bits/stdc++.h>#define MAXN 100#define ll long longusing namespace std;int main() {    ll n, m, u, v, ans;    int T;    scanf("%d", &T);    while (T--) {        scanf("%lld %lld", &n, &m);        if (m < n - 1) {            ll a = n - m - 1;            ans = m + m * (m - 1);            ans += (m + 1) * a * n + a * (a - 1) / 2 * n;        } else {            m = min(n * (n - 1) / 2, m);            ans = m + (n * (n - 1) / 2 - m) * 2LL;        }        printf("%lld\n", 2 * ans);    }}

Rikka with Subset

再次读错题系列
开场10分钟队友读出了神奇的题意。然后就挂机4小时在这题上。
题目中神奇的is。。

题意:
给出一个A序列,表示i这个数的通过B序列组合成的方式有多少种。
比如样例1 1 1
0有1种,1有1种,2有1种

现在要你找回B序列。并按照字典序从小到大输出

思路:
其实如果反过来。给你B序列。让你求i的组合数。应该都会把。。对MAX{Bi}进行简单01背包即可
现在就是给你背包出来的情况。让你求原本序列。
其实我们把他们当做反向背包求即可。
比如1有3种。那么1一定是从0状态转移过来的。
那么一定有3个1。
如果1有0种。2有两种。那么2肯定不可能由1转移过来。因为1都不存在情况数。肯定从0转移过来。
所以一定有2个2。
从前往后。每次dp减去上一次情况数即可。

#include <bits/stdc++.h>#define MAXN 10005using namespace std;int main() {    int T, n, m, b[MAXN];    scanf("%d", &T);    while (T--) {        scanf("%d %d", &n, &m);        for (int i = 0; i <= m; i++) {            scanf("%d", &b[i]);        }        while (n--) {            int ans = 0;            for (int i = 1; i <= m; i++) {                if (b[i]) {                    ans = i;                    break;                }            }            printf("%d", ans);            if (n) {                printf(" ");            }            for (int i = ans; i <= m; i++) {                b[i] -= b[i - ans];            }        }        puts("");    }} 

Rikka with Competition

全场签到题再次落到了第11题。
题意:
有n个人。他们每个人的能力值为ai。他们之间一共有n - 1场比赛。每场比赛如果|aiaj|>K的话。那么能力值那个人获胜,否则两个人都有可能获胜。问有多少个人可能可以赢得比赛

思路:
排个序。每场比赛从最后那个人开始看。如果他满足aiaj <= K那么他们都有机会可能赢。
但是一旦有个人他赢得了比赛。那么前面所有人肯定都满足aiaj>K。所以一旦不满足aiaj <= K结束记录答案即可。

#include <bits/stdc++.h>#define MAXN 100005using namespace std;int main() {    int T, n, k, num[MAXN];    scanf("%d", &T);    while (T--) {        scanf("%d %d", &n, &k);        int ans = 1;        for (int i = 0; i < n; i++) {            scanf("%d", &num[i]);        }        sort(num, num + n);        for (int i = n - 1; i >= 1; i--) {            if (num[i] - num[i - 1] <= k) {                ans++;            } else {                break;            }        }        printf("%d\n", ans);    }}