標籤:比賽總結
福州大學第十一屆程式設計競賽
Contest Finished!
Tag |
Pro.ID |
Problem Title |
Ratio(AC/Submit) |
|
1 |
大王叫我來巡山呐 |
80.31%(261/325) |
|
2 |
防守陣地 I |
23.48%(193/822) |
|
3 |
shadow |
13.23%(97/733) |
|
4 |
花生的序列 |
12.07%(21/174) |
|
5 |
防守陣地 II |
14.98%(68/454) |
|
6 |
巡了南山我巡北山 |
0.00%(0/45) |
|
7 |
Nostop |
20.79%(21/101) |
|
8 |
卷福的難題 |
10.00%(1/10) |
本來打算當作組隊賽來做的,結果隊友有足球賽,還有一個有黨校。。只剩下我一個人單挑了。 @[email protected] 還好不是很難,不然就被虐翻了。。整體來說題目比較簡單,應該本來就是作為個人賽準備的。。
A題籤到題
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 5;const int INF = 0x3f3f3f3f;int main(){ int n; while(scanf("%d", &n) != EOF) { int ans = n / 7 * 2; if(n % 7 == 6) ans ++; printf("%d\n", ans); }}
B題觀察式子轉移,就可以很容易發現端倪了。。
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 1001000;const int INF = 0x3f3f3f3f;int a[maxn];int main(){ int n, m; while(scanf("%d%d", &n, &m) != EOF) { int ans = 0, tot = 0, sum = 0; for(int i = 1; i <= m; i ++) { scanf("%d", &a[i]); sum += a[i]; tot += i*a[i]; } ans = tot; for(int i = m + 1; i <= n; i ++) { scanf("%d", &a[i]); tot -= sum; sum -= a[i - m]; sum += a[i]; tot += a[i] * m; ans = max(ans, tot); } printf("%d\n", ans); }}
C題是比較簡單的樹dp吧,只需要看孩子和本身有沒有士兵,有的話當前點肯定會被消滅。OJ比較奇特,遞迴會爆棧,用vector會逾時。。不幸的是兩種情況我都遇到了。。
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define MP make_pair#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 100100;const int INF = 0x3f3f3f3f;int arm[maxn];bool hav[maxn];struct Edge{ int u, v;}E[maxn*2];int fir[maxn], nxt[maxn*2], tot = 0;LL d[maxn];void AddEdge(int u, int v){ E[tot].u = u, E[tot].v = v; nxt[tot] = fir[u], fir[u] = tot ++;}LL dfs(){ stack<pair<int, int> > S; CLR(d, 0); S.push(MP(1, 0)); int cnt = 0; while(!S.empty()) { int u = S.top().first, fa = S.top().second; if(fir[u] == -1) { if(hav[u]) hav[fa] = 1, d[fa] += d[u] + arm[u]; S.pop(); } else { int v = E[fir[u]].v; fir[u] = nxt[fir[u]]; if(v == fa) continue; S.push(MP(v, u)); } } return d[1];}int main(){ int n, k; while(scanf("%d%d", &n, &k) != EOF) { for(int i = 1; i <= n; i ++) { scanf("%d", &arm[i]); } CLR(hav, 0);CLR(fir, -1); tot = 0; for(int i = 0; i < k; i ++) { int u; scanf("%d", &u); hav[u] = 1; } for(int i = 1; i < n; i ++) { int u, v; scanf("%d%d", &u, &v); AddEdge(u, v); AddEdge(v, u); } printf("%lld\n", dfs()); }}
D題算是一道dp吧,dp[i][j],表示到第i為為止,有j個屬於第一個串,因為串的特殊性(WBWBWB),所以很容易判斷當前位置的字母滿足的情況。比如當前j為奇數,那麼j後面肯定只能接B。。。就這樣。。。
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 10100;const int INF = 0x3f3f3f3f;const int MOD = 1000000007;char ch[maxn];int dp[2][3300];int main(){ int T, n; scanf("%d", &T); while(T --) { scanf("%d%s", &n, ch); CLR(dp, 0); dp[0][0] = 1; for(int i = 0, j = 1; i < n * 2; i ++, j ++) { CLR(dp[j&1], 0); if(ch[i] == ‘B‘) { for(int k = 0; k <= n; k ++) { if(k&1) dp[j&1][k+1] = (dp[j&1][k+1] + dp[i&1][k]) % MOD; if((i-k)&1) dp[j&1][k] = (dp[j&1][k] + dp[i&1][k]) % MOD; } } else { for(int k = 0; k <= n; k ++) { if((k&1) == 0) dp[j&1][k+1] = (dp[j&1][k+1] + dp[i&1][k]) % MOD; if(((i-k)&1) == 0) dp[j&1][k] = (dp[j&1][k] + dp[i&1][k]) % MOD; } } } printf("%d\n", dp[0][n]); }}
E裸線段樹區間更新,區間查詢,只要你不想那麼多,就可以直接A掉。
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1using namespace std;const int maxn = 100100;const int INF = 0x3f3f3f3f;int add[maxn<<2];int sum[maxn<<2];void PushUp(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void PushDown(int rt,int m){ if (add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; sum[rt<<1] += add[rt] * (m - (m >> 1)); sum[rt<<1|1] += add[rt] * (m >> 1); add[rt] = 0; }}void build(int l,int r,int rt){ add[rt] = 0; if (l == r) { scanf("%d",&sum[rt]); return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt);}void update(int L,int R,int c,int l,int r,int rt){ if (L <= l && r <= R) { add[rt] += c; sum[rt] += c * (r - l + 1); return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson); if (m < R) update(L , R , c , rson); PushUp(rt);}int query(int L,int R,int l,int r,int rt){ if (L <= l && r <= R) { return sum[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; LL ret = 0; if (L <= m) ret += query(L , R , lson); if (m < R) ret += query(L , R , rson); return ret;}int main(){ int n, m, q; while(scanf("%d%d%d", &n, &m, &q) != EOF) { build(1, n, 1); for(int i = 0; i < q; i ++) { int x; scanf("%d", &x); printf("%d\n", query(x, x + m - 1, 1, n, 1)); update(x, x + m - 1, -1, 1, n, 1); } }}
F應該是搜尋吧。。。感覺無從下手,罪過。。。大致思路應該是判斷是否是子串,然後在進行加字元,copy操作吧。。。我猜的。。
G題這種題第一次見到,感覺自己YY出來還是很高興的!就是用矩陣來表示走K步之後的各個點對到達所需要的最小花費。這樣的話,我們就可以用初始矩陣(表示的是1步到達的情況)不斷更新,來獲得走2步,走3步的到達情況。。這樣的話思路就很明確了。因為題目資料比較大,我們直接用快速冪更新就可以了。(應該很容易想到這些更新是滿足結合率的吧)。我還是覺得看代碼清楚些。。這個OJ很個性,用lld,wa了無數次,改成cin,cout才過。。。=.=!!
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define MP make_pair#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 55;const LL INF = 1ll << 60;struct Matrix{ LL m[maxn][maxn];}sol, pre;int n;Matrix Add(Matrix a, Matrix b){ Matrix ret; for(int i = 1; i <= n; i ++) { for(int j = 1; j <= n; j ++) { ret.m[i][j] = INF; LL& tmp = ret.m[i][j]; for(int k = 1; k <= n; k ++) { tmp = min(tmp, a.m[i][k] + b.m[k][j]); } } } return ret;}Matrix Mul(Matrix a, int n){ Matrix ret; bool flag = false; while(n) { if(n & 1) { if(flag) ret = Add(ret, a); else ret = a; flag = true; } a = Add(a, a); n >>= 1; } return ret;}void pt(Matrix sol){ for(int i = 1; i <= n; i ++) { for(int j = 1; j <= n; j ++) printf("%lld ", sol.m[i][j]); puts(""); }}int main(){ int h, k, T; scanf("%d", &T); while(T --) { scanf("%d%d%d", &n, &h, &k); for(int i = 1; i <= n; i ++) { for(int j = 1; j <= n; j ++) sol.m[i][j] = INF; } for(int i = 0; i < h; i ++) { int u, v;LL c; scanf("%d%d", &u, &v); cin >> c; sol.m[u][v] = min(sol.m[u][v], c); } sol = Mul(sol, k); if(sol.m[1][n] == INF) puts("-1"); else cout << sol.m[1][n] << endl; //printf("%lld\n", sol.m[1][n]); }}
H題完全沒想法,最後絕殺的那個人真厲害,ORZ~~
Android應用基礎學習記錄