DAY2-補題

卡布叻-空白發表於2024-10-02

我補題AK了,但你出言不遜是

非常好的一套題,讓我的大腦旋轉啊。

不太想開一個文章單獨屑,所以扔到隨筆裡面。

敲字速度有待加強。

說在前面

題目難度單調遞減,分數單調遞減。果然屑死了。

T1再次讀題失誤,正確的來說是程式碼敲得非常抽象。T2DP但沒騙到分非常不好,T3場上想出正解了,但推一半搞差分然後還沒有過掉,後面跟老師討論時發現想複雜了。其實T3在推出差分前一步停就是正解,但還是沒停下。T4可能是思維難度較小的,敲了個二分拿到15,但同機房有敲if過掉就顯得資料很水。

T1-下棋(chess)

看得出來出題人對這個機制的熱愛了。

題意一般簡單,扔洛谷可能就是紅。但為什麼沒過掉就是一個好問題了。

我現在試圖揣測上午的思路,可能是打的時候沒有算上進位之後加上來的三星(屑屑屑。

考試的時候成功推出式子,成功打上式子,但沒算進位,於是根據有理數乘法法則,搓掉了。

放一下考試的歪解:

#include <bits/stdc++.h> 
#define int long long
using namespace std;
struct Node {
	int x, y;
}book[100005];
bool cmp(Node a, Node b) {
	if(a.x != b.x) return a.x > b.x;
	return a.y < b.y;
}
signed main() {
	int n;
	cin >> n;
	for(int i = 1; i <= n; i ++) {
		int a,b,c;
		cin >> a >> b >> c;
		int a1 = (a % 3);
		int a2 = (a / 3) + (b % 3);
		int a3 = (a2 + b) / 3 + c;
		int ad = a1 + a2 * 3 + a3 * 18;
		book[i].x = ad;
		book[i].y = i;
	}
	sort(book + 1, book + n + 1, cmp);
	for(int i = 1; i <= n; i ++) {
		cout << book[i].y << " ";
	}
	return 0;
}

老師一開始說可能輸入反了,然後轉了三回之後發現式子假掉了。於是打式子。

正解:

#include <bits/stdc++.h> 
#define int long long
using namespace std;
struct Node {
	int x, y;
}book[100005];
bool cmp(Node a, Node b) {
	if(a.x != b.x) return a.x > b.x;
	return a.y < b.y;
}
signed main() {
	int n;
	cin >> n;
	for(int i = 1; i <= n; i ++) {
		int a,b,c;
		cin >> a >> b >> c;
		int a1 = (a % 3);
		int a2 = ((a / 3) + (b % 3)) % 3;
		int a3 = (a / 3 + b) / 3 + c;
		int ad = a1 + a2 * 3 + a3 * 18;
		book[i].x = ad;
		book[i].y = i;
	}
	sort(book + 1, book + n + 1, cmp);
	for(int i = 1; i <= n; i ++) {
		cout << book[i].y << " ";
	}
	return 0;
}

程式碼個人習慣很重,抱歉(輕輕跪下。

T2-汪洋(BigWater)

當時看到名稱的時候驚了,為什麼大寫就很迷。看題面發現了似乎是出題人藏的彩蛋。

BilibiliWorld 2023,簡稱BW

正好還是題目名稱好哎!彩蛋不錯。但 她可以和這些 coser 一起合影,然後發說說羨慕她那可憐的隊友,不是集郵之後發給沒搶到票的親友嗎?(樂我也沒搶到票,親友們也沒搶到就很悲

閒話見我的珂愛遊記,這裡不展開說了。

是的這道題又是DP。

又是和昨天一樣的問題,想出解法但切不掉。打臉。

希望明天想出解法能切掉。

題目分析後可以發現 Meowowco 走的是矩形,就可以遍歷所有邊然後求最大值,剪掉四個點就好了(因為是重複計算的所以剪掉

正解 :

#include <iostream>
using namespace std;
const int MAXN = 1005;
int a[MAXN][MAXN], row[MAXN][MAXN],col[MAXN][MAXN];
int main() {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j ++) {
            cin >> a[i][j];
            row[i][j] = row[i][j - 1] + a[i][j];
            col[i][j] = col[i - 1][j] + a[i][j];
        }
    }
    int ans = 0;
    for(int x = 1; x <= n; x ++) {
        for(int y = 1; y <= n; y ++) {
            ans = max(ans, row[1][y] + row[x][y] + col[x][1] + col[x][y] - a[1][1] - a[1][y] - a[x][1] - a[x][y]);
        }
    }
    cout << ans + 100;
    return 0;
}

T3-刪數(delnum)

考場想到正解,然後感覺假了就去敲暴力。中間敲了個差分然後發現cnt統計不進去於是騙分。

差分的思路就是設a[0] 為 0,於是後面每一個數的下一個要刪的數就是這個數和前一個數的差的絕對值,由於是單調遞增的自然數序列,所以差分可以求出來。

很神奇的cnt統計不進去,也就是他無法正確統計一輪而不是一個數字。

不過看了正解之後感受到了差分的麻煩以及時間複雜度高,不優的一個解法還讓我敲了最長的時間。

不如退回一步想正解。

正解:

沒辦法鴨子沒法複製又沒時間打,只能搞掉圖片了。

T4-平分糖果(candy)

這個題一眼列舉,於是Just do it.時間複雜度不算高,但只拿了15哭死。

二分思路很簡單,看看程式碼即可理解(簡稱太屑了以至於想不出來如何二分切掉這個題

#include <bits/stdc++.h>
#define int long long 
using namespace std;
signed main() {
//	freopen("candy.in", "r",stdin);
//	freopen("candy.out","w",stdout);
	int cnt = 1;
	while(1) {
		int fl = 0;
		int a[20], b[20000];
		for(int i = 1; i <= 6; i ++) {
			cin >> a[i];
			if(a[i] != 0) fl = 1;
		}
		if(fl == 0) return 0;
		cout << "Collection #" << cnt << ":" << endl;
		cnt ++;
		int sum = 0;
		int cnt1 = 0;
		for(int i = 1; i <= 6; i ++) {
			sum += a[i] * i;
			if(a[i] * i != 0) {
			   for(int j = 1; j <= a[i]; j ++) b[++cnt1] = a[i] * i;
			}
		}
//		cout << sum << endl;
//		for(int i = 1; i <= cnt1; i ++) cout << b[i] << endl;
		if(sum % 2 != 0) cout << "Can't be divided.\n\n";
		else {
			sort(b + 1, b + cnt + 1);
			int l = 1, r = cnt1;
	        sum /= 2;
	        int flag = 0;
			while(l < r) {
				int mid = (l + r) / 2;
			//	cout << b[l] << " " << b[r] << " " << b[l] + b[r] << endl;
				if(b[l] + b[r] == sum) {
					cout << "Can be divided.\n\n";
					flag = 1;
					break;
				}
				if(b[l] + b[r] > sum) {
					r = mid;
				} else {
					l = mid + 1;
				}
			}
			if(flag == 0) cout << "Can't be divided.\n\n";
		}
	}
//	fclose(stdin);
//  	fclose(stdout);
	return 0;
}

很奇怪的是二分最多時間超限,答案錯誤就很迷惑。老師看到了留個言解釋一下罷(攤

昨天二分暴力,今天暴力二分,果然rp守恆。

每個物品的數量有限,所以找出是否存在幾個物品的價值與物品總價值的一半相同就可以了,可以抽象成多重揹包。

很好的思路。為什麼考試寫不出來呢?

扔dp正解,思路詳細介紹會扔進tj裡面的(應該會的吧

#include <iostream>
using namespace std;
const int MAXN = 20005;
int a[10], dp[10][2 * MAXN], col = 0;
int main() {
    while (1) {
		int m = 0;
		for (int i = 1; i <= 6; i++) {
			cin >> a[i];
			m += a[i] * i;
		}
		if (!m) break;
		dp[0][0] = 1;
		for (int i = 1; i <= 6; i++)
			for (int k = 0; k <= a[i]; k++)
				for (int j = k * i; j <= m / 2 + 1; j++)
					dp[i][j] |= dp[i - 1][j - k * i];
		cout << "Collection #" << ++col << ':' << endl;
		if (m % 2 == 0 && dp[6][m / 2] == 1) cout << "Can be divided." << endl;
		else cout << "Can't be divided." << endl;
		cout << endl;
	}
    return 0;
}

賽後總結

總司令不知道什麼時候又出現了,大唐盛世如我所願。

T2出題老師彩蛋非常好,給無聊的做題新增了一點樂子。

這次模擬賽還是不理想啊不理想,究其原因可能是每次推到正解但不打,打一個莫名其妙的程式碼然後保靈。

希望明天會更好罷。

今天聽到好聽的神的隨波逐流,rp++。