我是比賽完後在去寫的
這是我第一次打洛谷月賽,之前一次是比賽完才去看而且寫了第一題就沒寫後面的了
284分,太水了,rank85左右
第一題第二題ac了,第三題寫了3^n的演算法,知道會超時,也知道滿分做法應該是只考慮有價值的狀態
但是還是沒想出正解,拿了70分
第四題想到了講評中說的錯誤的做法,然後細節比較多,怒剛1.5h,然而寫掛了,交上去14分……
還不如寫暴力有30~40分
考場策略出錯了,如果最後一道題考慮騙分,能上300(然而300分rank還是很後)
5分鐘ac。
簽到題,陣列都不用開。
寫的時候不太確定會不會答案非常大導致超時,但是直接交就ac了
好像有個什麼定理可以得出答案不會太大。反正我ac了就好
#include#define rep(i, a, b) for(register int i = (a); i < (b); i++)#define _for(i, a, b) for(register int i = (a); i <= b; i++)
using
namespace
std;
intmain()
}return0;
}
30分鐘ac
看完題腦中閃過貪心的念頭,但是後來看到資料範圍400,就去想n^3的dp了
然後最後折騰了一番,才發覺來回跳一定比順著跳要優。
那是不是一直來回跳就是最優的
然後我就猜了最高,最低,次高,次低……
然後就ac了。
大膽猜想!!
#include#define rep(i, a, b) for(register int i = (a); i < (b); i++)#define _for(i, a, b) for(register int i = (a); i <= b; i++)
using
namespace
std;
typedef
long
long
ll;const
int maxn = 300 + 10
;ll dp[maxn], a[maxn], ans;
intn;
intmain()
printf(
"%lld\n
", ans);
return0;
}
1h10min拿了70分
第一反應就是列舉子集,3^n
但是自己沒注意到一些細節,以及沒想清楚當前這個狀態的價值要乘上方案,所以一直調來調去
乙個小時左右才過了樣例
#include#define add(a, b) a = (a + b) % mod#define rep(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= b; i++)
using
namespace
std;
typedef
long
long
ll;const
int mod = 998244353
;const
int maxn = (1
<< 20) + 10
;int
dp[maxn], a[maxn], num[maxn], ans;
char
s[maxn];
intn, m;
intmain()
dp[0] = a[0
]; num[
0] = 1
; rep(s,
1, 1
}printf(
"%d\n
", dp[(1
<< n) - 1
]);
return0;
}
顯然會超時
可以只考慮有價值的狀態對答案的貢獻
顯然把包含這個狀態的方案數乘以這個狀態的價值就是對答案的貢獻
那麼考慮怎麼算方案
比如對於011
所有方案都是從000到011再到111
那麼考慮從000到011的方案
顯然是把兩個0變成兩個1的方案
更一般的來說,可以初始化出乙個陣列,num[i]表示把i個0變成i個1的方案數
考慮把j個0一起變成1
那麼有c(i, j) * num[i-j]種方案
那麼列舉j就可以了
現在想想其實不難,但是考試的時候就是沒想到
做題不夠多
#include#define add(a, b) a = (a + b) % mod#define rep(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= b; i++)
using
namespace
std;
typedef
long
long
ll;const
int mod = 998244353
;const
int maxn = 21
;ll c[maxn][maxn], num[maxn], ans;
char
s[maxn];
intn, m;
void
init()
num[
0] = 1
; _for(i,
1, 20
) _for(j,
1, i)
add(num[i], c[i][j] * num[i-j]);
}int
main()
printf(
"%lld\n
", ans);
return0;
}
大模擬……
大模擬就很考細心和碼力了
我一開始沒想到用並查集去維護這個東西,而想著用搜尋
所以**非常複雜,不能像並查集一樣很方便的實現合併操作
方向就錯了
然後我改題又改了n久
講幾個關鍵點
(1)把二維座標轉化為乙個數字,下標從1開始
#define id(x, y) (x - 1) * n + yint xx = (t1 - 1) / n + 1, yy = ((t1 - 1) % n) + 1;
(2)把氣的概念改一下。改成可以重複的,也就是說如果乙個格仔的不同方向有同乙個聯通塊,那就加多次,而不是加一次。這樣會非常方便
(3)巧用異或實現黑白棋的轉化
(4)可以把邊界的格仔設為'#',這樣很方便
(5)放棋子的時候,先減去周圍聯通塊的氣,再加上自己的。
(6)有幾種情況下不能放。賭死對方棋子。這個時候判斷一下對方棋子的氣是不是大於0就好
堵死己方棋子。這個地方尤為重要,我卡了很久。
如果放下去的棋子周圍有空格,那麼己方棋子一定存活,因為無論如何都有己方棋子的氣
如果有乙個己方棋子的聯通塊存活,那麼己方棋子一定存活。因為有些可能本來是死的,然後和己方棋子連到一塊就活了
因為最後是成乙個聯通塊的
#include#define id(x, y) (x - 1) * n + y#define rep(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= b; i++)
using
namespace
std;
const
int maxn = 600 + 10
;int dir[4][2] = ;
int gas[maxn * maxn], f[maxn*maxn], n;
char
a[maxn][maxn], s[maxn][maxn];
int find(int
x)void union(int i, int
j)void put(int x, int y, char
ch) rep(i,
0, 4
)
}bool can_put(int x, int y, char
ch)
for(map::iterator it = mp.begin(); it != mp.end(); it++)
return
ok;}
intmain()
}if(x[op] <= n && y[op] <=n)
else
op ^= 1
; }
return0;
}
總結(1)考場策略。到時候noip,第一題拿下,第二題盡量拿下,780分也行,第三題先打暴力的分,然後再想正解。
(2)相信自己的直覺,大膽猜想貪心
(3)用方案數乘以權值的方法計算對整體的貢獻
(4)用並查集維護聯通塊,想清楚,靜下心,一步步寫。
NOIP模擬賽 洛谷11月月賽
t1終於結束的起點 題解 列舉啊.斐波那契數 第46個爆int,第92個爆long long.發現結果一般是m的幾倍左右.不用擔心t。題解 貪心。從當前沒跳過的最高的和最低的之間來回跳。預計10分 include include include include define ll long long...
洛谷 9月月賽
題目描述 眾所周知,在一些特殊的部門,如果密碼能夠讓乙個人就解開,就會非常不安全。pic pre invoked code,預生成密碼 誕生了。這個密碼比較安全,是因為它必須由三個人保管。系統首先預先生成三個大整數a b c,計算出它們的與and 或or 和sum並儲存,然後將a b c分別告訴這三...
洛谷5月月賽
n堆石子,每次可以從第i堆中取走乙個當且僅當ni ni 1 第0堆視作0個 拿不了就輸了。問先手贏還是後手贏。奇偶性問題。不管如何分布,必定全部被拿完。include inline char gc return s inline int read while c 0 c 9 return x f i...