首页 > 其他分享 >[赛记] csp-s模拟5

[赛记] csp-s模拟5

时间:2024-09-29 08:55:20浏览次数:7  
标签:赛记 int res sum long sumb ans csp 模拟

光 100pts

赛时打的错解A了,就很神奇;

其实可以发现答案有可二分性,考虑二分答案,每次check时枚举左上角和右下角的耗电量,然后对左下角的耗电量再进行二分,最后判定以下即可;

赛时就这么打的,然后赛后拍出来了;

其实这个思路是对的,只是 $ \lfloor \frac n4 \rfloor $ 这个条件有误差,所以暴力在这个范围内判断一下即可;

时间复杂度:$ O(n^2 \log^2 n) $,常数极大,但是跑不满,可以过;

爬 10pts

直接暴搜10pts;

考虑正解,我们发现,能在某一个节点产生贡献的只有它自己和其直接儿子,所以只考虑这一部分即可;

因为是异或,考虑对值进行二进制拆分,依次考虑每一位的贡献;

假设现在考虑到第 $ k $ 位,设当前节点 + 其直接儿子为 $ tot $,其中这一位为 $ 1 $ 的数的个数有 $ sum $ 个;

先考虑当前节点不是根的情况:

那么只有当有奇数个这一位为 $ 1 $ 的数在这个节点时,这一位才能产生贡献,其它数咋跳都没有影响,这个方案数为:

\[(C_{sum}^{1} + C_{sum}^{3} + C_{sum}^{5} + ...) \times 2^{n - sum - 1} \]

其中:

\[C_{sum}^{1} + C_{sum}^{3} + C_{sum}^{5} + ... = 2^{sum - 1} \]

注意上面两项并不能合并(因为前一项是有值的,合并以后可能就没值了);

然后减去只有一个数的情况,考虑 $ sum $ 个数,每个数只上去一次,剩下的 $ tot - 1 $ 个数不动,其余的 $ n - tot - 1 $ 个数随便,方案数为:

\[sum \times 2^{n - tot - 1} \]

总方案数为:

\[2^{sum - 1} \times 2^{n - sum - 1} - sum \times 2^{n - tot - 1} \]

最后乘一个 $ 2^k $ 即可;

对于是根的情况,分奇偶讨论一下即可(因为根不能往上跳);

时间复杂度 $ \Theta(n \log 1000000000) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const long long mod = 1e9 + 7;
int n;
long long a[500005];
long long ans;
struct sss{
	int t, ne;
}e[200005];
int h[200005], cnt;
void add(int u, int v) {
	e[++cnt].t = v;
	e[cnt].ne = h[u];
	h[u] = cnt;
}
long long fac[100005], fav[100005], p[100005];
long long ksm(long long a, long long b) {
	long long ans = 1;
	while(b) {
		if (b & 1) ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}
long long C(long long n, long long m) {
	if (n == m) return 1;
	if (m == 0) return 1;
	if (n < m) return 0;
	return fac[n] * fav[m] % mod * fav[n - m] % mod;
}
int main() {
	freopen("climb.in", "r", stdin);
	freopen("climb.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	int xx;
	for (int i = 2; i <= n; i++) {
		cin >> xx;
		add(xx, i);
	}
	fac[0] = 1;
	fav[0] = 1;
	p[0] = 1;
	for (int i = 1; i <= n; i++) {
		fac[i] = fac[i - 1] * i % mod;
		fav[i] = ksm(fac[i], mod - 2);
		p[i] = p[i - 1] * 2 % mod;
	}
	for (int k = 30; k >= 0; k--) {
		for (int i = 1; i <= n; i++) {
			int sum = 0;
			int tot = 1;
			for (int j = h[i]; j; j = e[j].ne) {
				int u = e[j].t;
				tot++;
				if ((1 << k) & a[u]) sum++;
			}
			if (tot == 1) continue;
			if ((1 << k) & a[i]) sum++;
			if (sum == 0) continue;
			if (i == 1) {
				bool vis = ((1 << k) & a[i]);
				if (vis) {
					long long o = 0;
					o = ((p[max(0, sum - 2)] * p[max(0, n - sum)] % mod - p[max(0, n - tot)]) % mod + mod) % mod;
					ans = (ans + (1 << k) * o % mod) % mod;
				} else {
					long long o = 0;
					o = (p[max(0, sum - 1)] * p[max(0, n - sum - 1)]) % mod;
					ans = (ans + (1 << k) * o % mod) % mod;
				}
			} else {
				long long o = 0;
				o = ((p[max(0, sum - 1)] * p[max(0, n - sum - 1)] % mod - sum * p[max(0, n - tot - 1)] % mod) % mod + mod) % mod;
				ans = (ans + (1 << k) * o % mod) % mod;
			}
		}
	}
	cout << ans;
	return 0;
}

字符串 50pts;

赛时 $ \Theta(Tn^4) $ 暴力DP 50pts也是没谁了;

正解是贪心;

因为对于 $ B $ 有 $ c $ 的限制,所以我们构造出一种形如以 $ c $ 个 $ B $ 和 $ 1 $ 个 $ A $ 为循环节,循环 $ i $ 次的字符串;

如:当 $ c = 3 $ ,$ i = 2 $ 时,我们构造出的字符串为 $ BBBABBBA $,特别的,当 $ i = 1 $ 时,字符串是形如 $ BBBAAA $ ($ m $ 个 $ B $ 和 $ n $ 个 $ A $)的;

然后我们考虑枚举 $ i $,每次加入剩下的 $ A $ 和 $ B $;

先加 $ A $,从头加一个可以获得 $ 1 $ 的贡献,然后每剩下 $ a $ 个 $ A $ 就有 $ 1 $ 的贡献;

再加 $ B $,从末尾加一个可以获得 $ 1 $ 的贡献,然后先把循环节里的 $ B $ 补充成 $ b + 1 $ 的倍数并依据给的公式计算其贡献,然后每剩下 $ b $ 个 $ B $ 就有 $ 1 $ 的贡献;

有点细节需要注意;

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int t;
int n, m, a, b, c;
int ans, sum;
int main() {
	freopen("string.in", "r", stdin);
	freopen("string.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--) {
		cin >> n >> m >> a >> b >> c;
		ans = 0;
		for (int i = 0; i <= min(n, m / c); i++) {
			sum = 0;
			if (i == 0) {
				sum++;
				sum += (n - 1) / a;
				sum += (m - 1) / b;
				sum++;
				ans = max(ans, sum);
				continue;
			}
			sum++;
			sum += (2 * i - 1);
			int suma = n - i;
			if (suma > 0) {
				sum++;
				suma--;
			}
			if (suma > 0) sum += (suma / a);
			int sumb = m - c * i;
			if (sumb > 0) {
				sumb--;
				sum++;
			}
			if (sumb > 0) {
				int o = c % b;
				int res = 0;
				if (o == 0) res = 1;
				else res = b + 1 - o;
				if (i * res >= sumb) {
					int ss = sumb / res;
					sum += ss * ((c + res - 1) / b);
					sum += (i - ss) * ((c - 1) / b);
				} else {
					sum += i * ((c + res - 1) / b);
					sumb -= res * i;
					sum += (sumb / b);
				}
			} else {
				sum += i * ((c - 1) / b);
			}
			ans = max(ans, sum);
		}
		cout << ans << '\n';
	}
	return 0;
}

奇怪的函数 30pts

赛时 $ \Theta(nq) $ 暴力能有30pts更是没谁了;

To be continued...

标签:赛记,int,res,sum,long,sumb,ans,csp,模拟
From: https://www.cnblogs.com/PeppaEvenPig/p/18438789

相关文章

  • csp模拟赛 6 9.28
    0+40+10+0一言以蔽之曰“一上午白干”T1一般图最小匹配首先,对答案有贡献的点对一定在排序后的位于相邻位置所以排序后取出所有\(a_{i+1}-a_{i}\)但不能像Kruskal一样每次取最小,因为其只需要考虑连通性,不涉及其它限制。所以用dp或者可反悔贪心取最优解点击查看代码#in......
  • 『模拟赛』csp-s模拟赛6
    『模拟赛』csp-s模拟赛6挂分日寄:0+20+0+0喵喵赛时对拍拍了10000个点都没拍出来,赛后一下就拍出错来了,我谔谔。T1DP喵~首先sort一遍方便处理其实转移时加一个abs取绝对值就可,纯纯多此一举设\(f[i,j,1/0]\)为前\(i\)个数中选\(j\)个的最小值若选当前这个数,则\(f[i......
  • 必可2024公益众筹赛2 之趋势赛记
    鲜花挂分挂麻了。赛时7:50~9:00开始先看第一题,看到第一题这么简短就想都没想直接开做了,到\(8:20\)左右的时候就想到可以直接字符串哈希,然后枚举插入字母的位置\(O(1)\)判断去除字母后两个串是否一样就可以了。然后就写写写,写的时候发现分讨插入字母的大致位置比较好些,于是......
  • 2024.9.28 代码源模拟赛
    省流:\(45+20+5+0=70\)简称:唐诗在此膜拜\(klz\)\(Heldivis\)\(Sorato\)\(czl\)\(Ech0\_7\)yxanslihe_qwq大佬T1先看的T1,想了一个拓排(其实是看错题了),然后过了第一个样例,然后咋调都过不去,就去码暴力了。过了大概10min发现看错题了,然后一会就想出来个\(O(n^2)\)......
  • 代码源 2024 CSP-S 模拟赛 Day 6
    赛时开T1,发现立即有了\(O(n^2)\)的思路,能有\(45\)分,但是先不急,看看后面的题。T2、T3、T4似乎都可以写个暴力。又想了想,T1还需要求出个LCA,所以复杂度是\(O(n^2\logn)\)的,开写。很快写完,调不过,边界很不好处理。直到\(1.5\)h才调出来\(O(n^2\logn)\)。上个厕所......
  • CSP-S 2024 第六次
    A排序之后只会选相邻的,直接DP。B从前往后考虑每个数\(a_i\)要不要删。若不删\(a_i\):若\(a_i\ne0\),则\(a_i\)已经确定。若\(a_i=0\),则\(a_i\)可取所有没出现过的数,以及\(i\)后最小的数(先删掉它再把\(a_i\)赋成它)若删掉\(a_i\):若\(a_{i+1}\ne0\),则\(a......
  • 『模拟赛』CSP-S模拟6
    Rank一般恼了怎么又狠狠挂分啊啊啊啊A.一般图最小匹配签。(这么多天终于签上了是吧)结论是,跟图完全没关系。题意转换完就是从\(n\)个数中选出\(m\)对差的绝对值之和最小的数。显然我们选的每一对数都应该是这\(n\)个数中相邻的一组,sort一下,设\(f_{i,j,k}\)表示到......
  • CSP-S 2022~2023 补题
    下面的代码都是远古代码,不打算重写了。CSP-S2023T1密码锁题意:一个密码锁上有\(5\)个位置,每个位置上的数字是\(0\sim9\)的循环,每次打乱会选择一或两个相邻位置同时循环移动。给定\(n\)个打乱后的状态,求有多少种可能的原状态。\(n\le8\)。容易发现可能的状态数......
  • [DMY]2024 CSP-S 模拟赛 Day 6
    前言离A掉一道题最近的一次。过程看完T1以后,想先构一个\(\mathcal{O}(n^3)\)的暴力,但是发现只有10pts,而且算法复杂度接近\(\mathcal{O}(n^4)\),所以果断放弃。把链的限制写了(然后亏大了),然后开始在CS上面画画。画了一会发现一个简单的dp思路,但是是\(\mathcal{O}(n^......
  • CSP & NOIP 模拟赛记录
    9.18(lanos212)T1签到,10mins内过了。T2乍一看有点困难,题目太形式化,不太直观,先跳过去思考T3了,T3没有什么DP的思路,但是这种题显然需要DP。看了一眼T4,被一堆式子糊脸恶心了,没有怎么思考。接下来一个小时在思考T2和T3,突然发现T2只需要每次求最短路就可以了,那么就是......