国庆のsurprise

感谢学长们

A. Rubyonly is always here

发现 \(a + b\) 的值不变,于是你会判无解

那么我们只要求出 \(ax + by = c\) 的最小操作次数即可

然后发现操作次数为 \(i\)\(x - y = 2^i\)

于是就有了暴力

赛后 \(Delov\) 告诉我,那个带入上面解方程即可,不过挂了

\(Lyin\) 大佬指出错误原因是 \(x - y = 2 ^ i\) 在计算取模之后不能保证,于是挂了,这也很好的解释了为啥在小模数时容易挂

解法褐的 \(lyin\) , 下面粘一下学长的题解,由于我太菜,就不粘我的垃圾代码了

image

B. Su_Zipei is always here

分块碾过去的,维护 \(sum_{l, r, k}\) 表示从 \(l\)\(r\) 的块内出现次数为 \(k\) 的数的个数,为了方便查询,对他最后一维,进行前缀和

\(cnt_{l, k}\) 表示前 \(l\) 个块, \(k\) 出现的次数

于是整块答案可以直接查询,散块开桶维护,当散块中元素个数+整块中元素个数 = k 时更新答案

正解考虑了根号分治,对于出现次数小于 \(\sqrt n\) 的用上面方法,多于的用 \(a_i <= 300\) 那个部分分类似方法维护

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
const int maxn = 100005;
int len = 3300, block;
int n, q, opt, a[maxn];
int cnt[32][maxn];
int ans = 0, t[maxn];
int sum[32][32][maxn];
int out[32];
void print(int x){
	int top = 0;
	while(x){out[++top] = x % 10; x /= 10;} if(top == 0)out[++top] = 0;
	for(int i = top; i > 0; --i)putchar('0' + out[i]);
	putchar('\n');
}
int main(){
	n = read(), q = read(), opt = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	block = (n + len - 1) / len;
	for(int i = 1; i <= block; ++i){
		int l = (i - 1) * len + 1, r = min(n, i * len);
		for(int j = 1; j <= n; ++j)cnt[i][j] = cnt[i - 1][j];
		for(int j = l; j <= r; ++j)++cnt[i][a[j]];
	}
	for(int l = 1; l <= block; ++l){
		for(int r = l; r <= block; ++r){
			for(int i = 1; i <= n; ++i)++sum[l][r][cnt[r][i] - cnt[l - 1][i]];
			for(int i = 1; i <= n; ++i)sum[l][r][i] += sum[l][r][i - 1];
		}
	}
	int ans = 0;
	for(int i = 1; i <= q; ++i){
		int l = read(), r = read(), k = read();
		l = (l + ans * opt - 1) % n + 1;
		r = (r + ans * opt - 1) % n + 1;
		if(l > r)swap(l, r);
		k = (k + ans * opt - 1) % n + 1;
		int bl = (l + len - 1) / len, br = (r + len - 1) / len;
		ans = 0;
		if(br - bl <= 1){
			for(int i = l; i <= r; ++i){++t[a[i]]; ans += t[a[i]] == k;}
			for(int i = l; i <= r; ++i)t[a[i]] = 0;
			print(ans);
			continue;
		}
		ans = sum[bl + 1][br - 1][n] - sum[bl + 1][br - 1][k - 1];
		int liml = bl * len, limr = (br - 1) * len + 1;
		for(int i = l; i <= liml; ++i){++t[a[i]]; ans += t[a[i]] + cnt[br - 1][a[i]] - cnt[bl][a[i]] == k;}
		for(int i = limr; i <= r; ++i){++t[a[i]]; ans += t[a[i]] + cnt[br - 1][a[i]] - cnt[bl][a[i]] == k;}
		for(int i = l; i <= liml; ++i)t[a[i]] = 0;
		for(int i = limr; i <= r; ++i)t[a[i]] = 0;
		print(ans);
	}
	return 0;
}

C. Kaiser_Kell is always here

比较原题,然后考场脑抽不会第一问

实际上,在修改时,因为 \(mex\) 单调,所以查询最后一个位置即可

关于更多细节可见原题

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
const int maxn = 1000005;
const int inf = 0x3f3f3f3f;
int n, a[maxn], q;
struct query{
	int l, r, id;
	friend bool operator < (const query &x, const query &y){
		return x.l < y.l;
	}
}que[maxn];
int ans[maxn];
bool vis[maxn];
int nxt[maxn], pos[maxn], mex[maxn];

struct tree{
	struct node{
		int val, tag;
	}t[maxn << 2 | 1];
	void built(int x, int l, int r){
		t[x].tag = inf;
		if(l == r){
			t[x].val = mex[l];
			return;
		}
		int mid = (l + r) >> 1;
		built(x << 1, l, mid);
		built(x << 1 | 1, mid + 1, r);
	}
	void push_down(int x){
		int ls = x << 1, rs = x << 1 | 1;
		t[ls].val = min(t[ls].val, t[x].tag);
		t[ls].tag = min(t[ls].tag, t[x].tag);
		t[rs].val = min(t[rs].val, t[x].tag);
		t[rs].tag = min(t[rs].tag, t[x].tag);
		t[x].tag = inf;
	}
	void modify(int x, int l, int r, int L, int R, int val){
		if(L > R)return;
		if(L <= l && r <= R){
			t[x].val = min(val, t[x].val);
			t[x].tag = min(t[x].tag, val);
			return;
		}
		if(t[x].tag != inf)push_down(x);
		int mid = (l + r) >> 1;
		if(L <= mid)modify(x << 1, l, mid, L, R, val);
		if(R > mid)modify(x << 1 | 1, mid + 1, r, l, R, val);
	}
	int query(int x, int l, int r, int pos){
		if(l == r)return t[x].val;
		int mid = (l + r) >> 1;
		if(t[x].tag != inf)push_down(x);
		if(pos <= mid)return query(x << 1, l, mid, pos);
		else return query(x << 1 | 1, mid + 1, r, pos);
	}
}t;

int main(){
	n = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	q = read();
	for(int i = 1; i <= q; ++i)que[i].l = read(), que[i].r = read(), que[i].id = i;
	sort(que + 1, que + q + 1);
	int mn = 1;
	for(int i = 1; i <= n; ++i){
		vis[a[i]] = 1;
		while(vis[mn])++mn;
		mex[i] = mn;
	}
	t.built(1, 1, n);
	for(int i = 1; i <= n; ++i)vis[i] = 0;
	for(int i = 1; i <= n; ++i)vis[mex[i]] = 1;
	for(int i = 1; i <= n; ++i)pos[i] = n + 1;
	for(int i = n; i >= 1; --i){
		nxt[i] = pos[a[i]];
		pos[a[i]] = i;
	}
	int p = 1;
	for(int i = 1; i <= n; ++i){
		while(p <= q && que[p].l == i){
			ans[que[p].id] = t.query(1, 1, n, que[p].r);
			++p;
		}
		t.modify(1, 1, n, i + 1, nxt[i] - 1, a[i]);
		vis[t.query(1, 1, n, nxt[i] - 1)] = 1;
	}
	mn = 1;
	while(vis[mn])++mn;
	printf("%d\n",mn);
	for(int i = 1; i <= q; ++i)printf("%d ",ans[i]);
	return 0;
}

D. Pl_er is always here

褐的

我是一个不会高数的废物

joke3579大佬的博客

密码是他真实姓名

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
const int maxn = 3000006;
const int mod = 1e9 + 7;

int fac[maxn], inv[maxn];
int qpow(int x, int y){
	int ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
	return ans;
}
int c(int n, int m){return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;}
int n;
int fd(int x, int k){return 1ll * qpow(x, n - k) * fac[n] % mod * inv[n - k] % mod;}
int gd(int x, int k){return 1ll * qpow(x, n + k) * fac[n + k] % mod * inv[n] % mod;}
int main(){
	n = read(); if(n == 0){printf("1\n");return 0;}
	fac[0] = inv[0] = 1; for(int i = 1; i <= n + n; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
	inv[n + n] = qpow(fac[n + n], mod - 2); for(int i = n + n - 1; i > 0; --i)inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
	int ans = 0, iv2 = qpow(2, mod - 2);
	for(int i = 0; i <= n; ++i){
		ans = (ans + 2ll * c(n, i) * fd(iv2, i) % mod * gd(2, n - i) % mod) % mod;
	}
	ans = 1ll * ans * qpow(iv2, n) % mod * inv[n] % mod;
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-10-01 21:38  Chen_jr  阅读(29)  评论(0编辑  收藏  举报