2024 信友队 noip 冲刺 8.30

拉了场 ARC 下来当模拟赛:/

T1

考虑 dp,设 f ( i , 0 / 1 ) f(i,0/1) f(i,0/1) 表示考虑到第 i i i 个元素,是正是负,再设一个 g ( i , 0 / 1 ) g(i,0/1) g(i,0/1) 表示 a i a_i ai 是正是负的方案数辅助转移。然后就做完了。

const int maxn = 1e5 + 5, P = 1e9 + 7;
int a[maxn], n;
int f[maxn][2], g[maxn][2];
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	f[1][0] = a[1], f[1][1] = 0, g[1][0] = 1, g[1][1] = 0;
	for (int i = 2; i <= n; i ++) { 
		g[i][0] = (1ll * g[i - 1][0] + g[i - 1][1]) % P, g[i][1] = g[i - 1][0];
		f[i][0] = ((1ll * f[i - 1][0] + 1ll * f[i - 1][1]) % P + 1ll * g[i][0] * a[i] % P) % P,
		f[i][1] = ((1ll * f[i - 1][0] + P) - 1ll * g[i][1] * a[i] % P) % P;
	}
	printf("%lld\n", (1ll * f[n][0] + 1ll * f[n][1]) % P);
	return 0;
}

T2

一眼盯真,把 x x x 取遍 a i 2 \cfrac{a_i}{2} 2ai 一定会取到最优解,从小到大排序,求个后缀和,分成 [ 1 , i ] [1,i] [1,i] [ i + 1 , 1 ] [i+1,1] [i+1,1] 两部分贡献,加起来求个 min ⁡ \min min 最后除以 n n n 即可。

const int maxn = 1e5 + 5, P = 1e9 + 7;
#define ll long long
int a[maxn], n;
ll sum[maxn];
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	sort(a + 1, a + n + 1); 
	for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i];
	double all_ans = 2e18;
	for (int i = 1; i <= n; i ++) {
		double x = a[i] / 2.0;
		double pre = x * i, suf = sum[n] - sum[i] - x * (n - i);
		if (pre + suf < all_ans) all_ans = pre + suf;
	} all_ans /= n;
	return printf("%.12lf", all_ans), 0;
}

T3

发现交替进行 3 , 4 3,4 3,4 操作增长速度最快,发现是斐波那契数列,一开始想的是构造数列的前两个元素,于是套了个 exgcd 求最小整数解,然后错完了。正解是考虑在交替过程中插入 1 , 2 1,2 1,2 操作进行微调,发现在交替过程中插入一个 + 1 +1 +1 操作,再执行 k k k 轮会使增量变成 f ( k ) f(k) f(k),把 n n n 拆成若干 f f f 的项的和,交替过程中预判和讨论一下是否需要插入 + 1 +1 +1 操作即可。操作次数刚好卡到上限。

#define int long long //:/
const int maxn = 87;
int fib[maxn], n; bool chs[maxn];
signed main() {
	fib[1] = 1;
	for (int i = 2; i < maxn; i ++) 
		fib[i] = fib[i - 1] + fib[i - 2];
	scanf("%lld", &n);
	for(int i = maxn - 1; i >= 1; i --) 
		if (n >= fib[i]) 
		 	chs[i] = 1, n -= fib[i];
	vector<char> ans; bool apr = 0;
	if (chs[maxn - 1]) ans.push_back(2), apr = 1;
	for (int i = 1; i <= (maxn >> 1); i ++) {
		if (apr) ans.push_back(4), ans.push_back(3);
		if (chs[(maxn - 1) - i * 2 + 1]) ans.push_back(1), apr = 1;
		if (chs[(maxn - 1) - i * 2]) ans.push_back(2), apr = 1; 
	} printf("%d\n", ans.size());
	for (auto x : ans) printf("%d\n", x);
 	return 0;
}

T4

赛时并没有想出来。观察到 Alice 非常被动,没有绝对的最大化策略,于是被 Bob 薄纱,只需考虑最小化即可,原题从博弈论变成两两分组使得异或值的最大值最小。贪心地从最高位开始考虑,然后在 01Trie 上神奇分类讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值