国庆のsurprise
感谢学长们
A. Rubyonly is always here
发现 \(a + b\) 的值不变,于是你会判无解
那么我们只要求出 \(ax + by = c\) 的最小操作次数即可
然后发现操作次数为 \(i\) 时 \(x - y = 2^i\)
于是就有了暴力
赛后 \(Delov\) 告诉我,那个带入上面解方程即可,不过挂了
\(Lyin\) 大佬指出错误原因是 \(x - y = 2 ^ i\) 在计算取模之后不能保证,于是挂了,这也很好的解释了为啥在小模数时容易挂
解法褐的 \(lyin\) , 下面粘一下学长的题解,由于我太菜,就不粘我的垃圾代码了
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
褐的
我是一个不会高数的废物
密码是他真实姓名
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;
}