日常讀錯題,賽後一個鐘還是不懂爲何是簽到題。
爲什麼你們都能過簽到題啊。
爲什麼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);
}
}