11.18 解题报告

总的来说没挂分,因为没啥分可以挂了。

预计得分 : 60 + 0 + 20 + 20

实际得分: 60 + 0 + 15 + 20

A

预计得分 : 60

实际得分: 60

写了 n^2 的暴力 + 特殊性质

特殊性质用暴力来写的,看了一下可以 \(\mathcal{O}(n)\) 推。

更正的代码:
想起来了,我没更正代码:

#include <bits/stdc++.h>
#define pb push_back
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
typedef long long ll;

const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
inline int read() {
	int res = 0, f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) f |= (ch == '-');
	for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch - '0');
	return f ? -res : res;
}

int n, a[N], b[N];
ll ans = 0, dp[N];

namespace Sub1 {
	void Main() {
		ll cur = 10, js = 5;
		dp[1] = 0, dp[2] = 1, dp[3] = 4, dp[4] = 10;
		for(int i = 5; i <= n; i++) dp[i] = dp[i - 1] + cur, cur = (cur + js), js++;
		cout << dp[n] << '\n';
		exit(0); 
	}
}

signed main() {
	freopen("swap.in", "r", stdin);
	freopen("swap.out", "w", stdout);
	n = read();
	for(int i = 1; i <= n; i++) b[i] = n - i + 1;
	for(int i = 1; i <= n; i++) a[i] = read();
	int f = 0;
	for(int i = 1; i <= n; i++) f |= (a[i] != b[i]);
	if(!f) Sub1::Main();
	for(int i = 1; i <= n; i++) {
		if(a[i] == i) continue;
		int wz = 0; 
		for(int j = i + 1; j <= n; j++) 
			if(a[j] == i) { wz = j; break;}
		for(int j = wz; j > i; j--) ans += abs(a[j] - a[j - 1]), swap(a[j], a[j - 1]); 
	}
	cout << ans << '\n';
	return 0;
}

/*
	这是一个 1~n 的排列
	就是转换成了给你一个序列,把他变成 1~n 的序列
	每个位置该去哪已经固定了 
	那怎样能使代价最小呢/hsh
	昨晚做了个一样的题,那个是 n^2 的做法
	先写个 n^2 的暴力看看 
	写完暴力了,感觉就是对于前后差值绝对值的一段区间进行翻转?
	好像是套个文艺平衡树就可以在 n log n 做完了
	可惜我早忘了怎么写了 /hsh 
	看看特殊性质的分数怎么写吧
	现在有 60 分	
	特殊性质是倒序排列的 
	可以 O(n) 推出来 
	3 
	3 2 1
	4
	
	4 
	4 3 2 1
	10
	
	5 
	5 4 3 2 1
	20
	
	6
	6 5 4 3 2 1
	35
	
	7 
	7 6 5 4 3 2 1
	56
	
	8
	8 7 6 5 4 3 2 1
	84
        3 4  5  6   7 8  9   10   11	
	0 1 4 10 20 35 56 84 120 165 220 + 286
	1 3 4 6 10 15 21 28 + 36 + 45 + 55 + 66
	       4 + 5 + 6 + 7 + 8 + 9 + 10 + 11
*/

B

搜索太难写了,写了很长时间没草出来了。

#include <bits/stdc++.h>
#define pb push_back
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;

#define int long long
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int Mod = 998244353;

inline int read() {
	int res = 0, f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) f |= (ch == '-');
	for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch - '0');
	return f ? -res : res;
}
/*
	n = k 和 k <= 20 的话,感觉比较好写?
	k = 20 的话就是暴力了吧 
	n = k 说明了只要能选到 1 位置就行了
	于是特殊性质的题目就转换成了:
	有 n 个数字,期望多少轮能选 1
	n <= 500 
	先手摸几组算算吧/hsh
	第一轮选1的期望+第二轮选1的期望+……+第n轮选1的期望就是答案
	1/n * 1 +  (n - 1) * 1 / (n - 1) * 2 + 
	感觉不是很好写啊,没学过数学期望 /hsh 

*/

int n, k, a[N];
int fz, fm;
std::bitset <N>  vis;

inline int gcd(int a, int b) {
	return !b ? a : gcd(b, a % b);
} 

inline void tf(int &a, int &b, int c, int d) {
	if(!a || !b) { a = c, b = d; return;}
	int	FM = b * d, Fz = a * d + b * c;
	a = Fz, b = FM;
	int Gcd = gcd(a, b);
	a /= Gcd, b /= Gcd; 
}

inline int ksm(int a, int b) {
	int res = 1;
	while(b) {
		if(b & 1) res = (res * a) % Mod;
		a = (a * a) % Mod, b >>= 1; 
	} return res % Mod;
} 

// Start: 10:35 Finish: 
// 首先要知道这是第x轮把1拿走,然后只会造成 x / sum 的贡献
// 直接强行用分数来替换成整数做就行了吧
// 问题是找能到达的最近的棋子。
// 1 1 0 1 1 0 
// 破环成链然后从左边找,从右边找就行了
// 我觉得应该是给了 dfs 15 分,whq 不能这么绝情/hsh
// 现在还有 1.5h 我还有2个题的暴力没有写啊/fn
// 不会写 dfs啊,看不懂样例
// 首先每一轮都会把一个棋子整没
// 所以搜索最多搜索 k 层
 
inline int get(int pos) {
	int l = pos, r = pos;
	for(int i = pos; i >= 1; i--) 
		if(vis[i]) { l = i;	break;}
	for(int i = pos; i <= 2 * n; i++) 
		if(vis[i]) { r = i; break;}
	if(pos - l <= r - pos) return l;
	else return r;	
}

inline void cclear(int x) {
	if(x >= 1 && x <= n) vis[x] = vis[x + n] = 0;
	else vis[x] = vis[x - n] = 0;
} 

inline void Cover(int x) {
	if(x >= 1 && x <= n) vis[x] = vis[x + n] = 1;
	else vis[x] = vis[x + n] = 1;
}

bool qwq[N];
 
// 写不出 T2 的期望爆搜了 /hsh
// 再写30min,写不出来就溜了/hsh
// 真的不会写啊,现在的得分情况最优是 60 + 0 + 0 + 20 还没过百啊 /hsh
// 光写一下 n = k 的部分分吧
// sb 才写,去写一下 T3 的20分
// 现在最优得分是 : 60 + 0 + 20 + 20 = 100 /jy 
// mb 啥也不会写,出的题很好,就是我看不大懂题目/hsh
// md 光在写碎碎念了,题到是没写多少/hsh

// 40 分钟我先去理解一下题目吧
// 最后10分钟的时候我去收拾文件夹
 
inline void dfs(int step, int Sum, int pre) {
	if(step == k + 1) {
		tf(fz, fm, pre, Sum);
		return;
	} 
	for(int i = 1; i <= n; i++) {
		int wz = get(i);
		cclear(wz);
		if(pre == 1) dfs(step + 1, Sum * n % Mod, pre * n % Mod);
		else if(wz == 1) dfs(step + 1, Sum * n % Mod, 1);
		else dfs(step + 1, Sum * n % Mod, pre);
		Cover(wz);
	}
} 
signed main() {
	freopen("game.in", "r", stdin);
	freopen("game.out", "w", stdout);
	n = read(), k = read();
	for(int i = 1; i <= k; i++) a[i] = read(), vis[a[i]] = 1;	
	for(int i = 1; i <= n; i++) vis[i + n] = vis[i];
	dfs(1, 1, 0);
	cout << (fz * ksm(fm, Mod - 2)) % Mod;
	putchar('\n'); 
	return 0;
}

C

一个很难读懂题的题。

读了很长时间,猜了个意思,然后过了大样例就跑了。

#include <bits/stdc++.h>
#define pb push_back
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
typedef long long ll;

const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int Mod = 998244353;

inline int read() {
	int res = 0, f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) f |= (ch == '-');
	for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch - '0');
	return f ? -res : res;
}

struct Edge { int v, nxt;} e[N]; 
ll ans = 0;
int n, type, head[N], num_edge = 0, siz[N], fa[N];
inline void add_edge(int u, int v) { e[++num_edge] = (Edge) { v, head[u]}, head[u] = num_edge;}
 
inline void dfs(int u, int Fa) {
	fa[u] = Fa;
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if(v == Fa) continue;
		siz[u]++;
		dfs(v, u); 
	}  
}  

struct qwq {
	int a, b, c, d;
} p[N];

int stc[N], sc = 0;

int ans1, ans2 = 0;
int cnt[N];
namespace Sub2 {
	void Main() {
		for(register int b = 1; b <= n; b++) {
			int a = fa[b];
			for(register int i = head[a]; i; i = e[i].nxt) {
				int c = e[i].v;
				if(c == b || c == fa[a]) continue;
				for(int j = head[b]; j; j = e[j].nxt) {
					int d = e[j].v;
					if(d == a) continue;
					p[++ans] = (qwq) {a, b,c, d};  
					if(ans > Mod) ans -= Mod;
				}
			}
		}
	}
}
// 我再把这些满足条件的四元组去dfs,然后判断?
// 那这样有20分,好像可以过100了 
// 有20分了/fn 

bool Check(qwq a, qwq b) {
	cnt[a.a] = 0, cnt[a.b] = 0, cnt[a.c] = 0, cnt[a.d] = 0, cnt[b.a] = 0, cnt[b.b] = 0, cnt[b.c] = 0, cnt[b.d] = 0;
	cnt[a.a]++, cnt[a.b]++, cnt[a.c]++, cnt[a.d]++, cnt[b.a]++, cnt[b.b]++, cnt[b.c]++, cnt[b.d]++;
	if(cnt[a.a] > 1 || cnt[a.b] > 1 || cnt[a.c] > 1 || cnt[a.d] > 1) return false;
	if(cnt[b.a] > 1 || cnt[b.b] > 1 || cnt[b.c] > 1 || cnt[b.d] > 1) return false;		
	return true;
}

bool Judge() {
	for(int i = 1; i <= sc; i++) {
		for(int j = i + 1; j <= sc; j++) {
			if(!Check(p[stc[i]], p[stc[j]]))return false;		
		}
	}	
	return true;
}

inline void Dfs(int step) {
	if(step == ans + 1) {
		if(Judge()) {
			ans1++, ans2 += sc;
			if(ans1 > Mod) ans1 -= Mod;
			if(ans2 > Mod) ans2 -= Mod;	
		}
		return;
	}
	stc[++sc] = step;
	Dfs(step + 1);
	--sc;
	Dfs(step + 1);	
}

// /hsh 
signed main() {
//	return system("fc ex_tree2.out ans.out"), 0;
//	freopen("tree.in", "r", stdin);
//	freopen("tree.out", "w", stdout); 
	n = read(), type = read();
	for(int i = 1; i <= n - 1; i++) {
		int u = read(), v = read();
		add_edge(u, v), add_edge(v, u);
	} 
	dfs(1, 0);
	Sub2::Main();
	Dfs(1);
	cout << ans1 % Mod << '\n';
	if(type == 1) cout << ans2 % Mod << '\n';
	return 0;
} 

D

// Start:10:10 Finish: 10:28 Score:20pts  
#include <bits/stdc++.h>
#define pb push_back
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;

const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;

inline int read() {
	int res = 0, f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) f |= (ch == '-');
	for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch - '0');
	return f ? -res : res;
}
 
int dis[N];
struct Node { int v, nxt;} e[N];
int n, q, head[N], num_edge = 0, top[N], son[N], fa[N], siz[N], dep[N];
inline void add_edge(int u, int v) { e[++num_edge] = (Node) {v, head[u]}, head[u] = num_edge;}
inline void dfs1(int u, int Fa, int w) {
	fa[u] = Fa, dep[u] = dep[Fa] + 1, siz[u] = 1, dis[u] = dis[Fa] + w;
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if(v == Fa) continue;
		dfs1(v, u, 1);
		siz[u] += siz[v];
		if(siz[son[u]] < siz[v]) son[u] = v;
	} 
}
inline void dfs2(int u, int tp) {
	top[u] = tp; 
	if(son[u]) dfs2(son[u], tp);
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if(v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	} 
}
inline int LCA(int x, int y) {
	while(top[x] ^ top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]]; 
	} return dep[x] < dep[y] ? x : y;
}
inline int Dis(int x, int y) {
	int lca = LCA(x, y);
	return dis[x] + dis[y] - (dis[lca] << 1); 
}
signed main() {
//	return system("fc ex_atree2.out ans.out"), 0;
	freopen("atree.in", "r", stdin);
	freopen("atree.out", "w", stdout); 
	n = read(), q = read();
	for(int i = 1; i <= n - 1; i++) {
		int u = read(), v = read();
		add_edge(u, v), add_edge(v, u);
	}
	dfs1(1, 0, 0), dfs2(1, 0);
	while(q--) {
		int u = read(), v = read(), d = read();
		int ans = 0;
		for(int i = 1; i <= n; i++) { 
			ans += (Dis(u, i) <= d || Dis(v, i) <= d);	
		} 
		cout << ans, putchar('\n');
	}
	return 0;
}

posted @ 2022-11-18 21:33  TLE_Automation  阅读(23)  评论(0编辑  收藏  举报