日常读错题,赛后一个钟还是不懂为何是签到题。
为什么你们都能过签到题啊。
为什么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
我们把公式转换一下就是要求(Ai−k)%Bi=0 的情况数
我们可以枚举k。且当枚举到k的时候必须满足。Bi>k且Ai>k
我们可以将所有的Ai和Bi 都用bitset压缩一下。
每次a>>k相当于A数组里所有数都-k,去除掉小于0的。
剩下的那些跟已有的Bi 的因子且运算一下。就是当模的答案为k时(Ai−k)%Bi=0 的情况数。
具体可以看代码。
强行卡在3496ms过了。。
听说bitset没有区间操作。大神们都手写bitset
#include <bits/stdc++.h>
#define MAXN 50005
using 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 long
using 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 10005
using 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场比赛。每场比赛如果|ai−aj|>K 的话。那么能力值那个人获胜,否则两个人都有可能获胜。问有多少个人可能可以赢得比赛思路:
排个序。每场比赛从最后那个人开始看。如果他满足ai−aj <= K那么他们都有机会可能赢。
但是一旦有个人他赢得了比赛。那么前面所有人肯定都满足ai−aj>K 。所以一旦不满足ai−aj <= K结束记录答案即可。
#include <bits/stdc++.h>
#define MAXN 100005
using 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);
}
}