CSP-S模拟赛二总结(实际难度大于CSP-S)

T1

很简短,也很好做,第一题直接场切。

我的方法

首先要明确一件事:就是如果选了 ax,ya_{x,y}ax,y,那么就必然要选 ay,xa_{y,x}ay,x,所以第一步就在 ax,ya_{x,y}ax,y 的基础上加上 ay,xa_{y,x}ay,x

然后我们把每个数看做一个点,任意两个点之间都建一条边(假想的),那么选集合就相当于在跑团,而每条边的权值就是 aaa,然后就把最大团问题改编一下就行了。

代码:

#include<bits/stdc++.h>
#define int long long
#define code using
#define by namespace
#define plh std
code by plh;
int c,t,n,ed,ans,a[26][26],vis[26];
void dfs(int x,int l)
{if(x>n){ans=max(ans,l);return;}int t=0;for(int i=1;i<x;i++){if(vis[i]){t+=a[i][x];}}vis[x]=1;dfs(x+1,l+t);vis[x]=0;dfs(x+1,l);
}
signed main()
{
//	freopen("party.in","r",stdin);
//	freopen("party.out","w",stdout);cin>>c>>t;while(t--){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];}}for(int i=1;i<=n;i++){for(int j=1;j<i;j++){int t=a[j][i]+a[i][j];a[i][j]=a[j][i]=t;ans=max(a[i][j],ans);}}dfs(1,0);cout<<ans<<endl;ans=-2e6;}return 0;
}

正解

看到 n≤20n\le20n20,你想到了什么?

看这里。

对了,状压 DP 啊!(虽然我在比赛的时候忘了还有 lowbit 这个东西然后写出了一个 O(2nn2)O(2^nn^2)O(2nn2) 的状压……)

首先定义状态:这一目了然了嘛,就是 dpsdp_sdpssss 表示当前的状态),其中 111 表示这个数被选进集合了,000 表示没有。

接着就是写状态转移方程,如果我们直接转移,那就会是 O(2nn2)O(2^nn^2)O(2nn2)(外层枚举状态 O(n2)O(n^2)O(n2),中间枚举加入集合的点 O(n)O(n)O(n),内层枚举集合内原本所含有的数与新的数所能构成的距离和 O(n)O(n)O(n)),明显只要是个正常的状压都会 TLE 的好吧,于是我们考虑优化。因为 O(2n)O(2^n)O(2n) 是肯定没法优化的,因此考虑优化一个 O(n)O(n)O(n)

明显,中间那一层枚举要加入的点可以直接优化成 O(1)O(1)O(1),因为枚举这一层实际上就是在找一个基准来计算,而这个基准又是随机的,因此我们可以直接固定下来:固定成 lowbit⁡(s)\operatorname{lowbit}(s)lowbit(s)(不知道 lowbit⁡\operatorname{lowbit}lowbit 的同学自己去找资料看看)。于是时间复杂度就被我们优化成了 O(2nn)O(2^nn)O(2nn)

但是简单一算就会发现:按照这个时间复杂度写时间复杂度就飙升到 200000000200000000200000000 左右了!还是过不了,于是再考虑优化。

我们先写出当前的状态转移方程:

dps=dps⊕lowbit⁡(s)+adp_s=dp_{s\oplus\operatorname{lowbit}(s)}+adps=dpslowbit(s)+a

后面那个 aaa 就表示 lowbit⁡(s)\operatorname{lowbit}(s)lowbit(s) 到每个点的距离和。

很明显,要想再优化,就要把这个 aaa 预处理出来。

那有没有一种办法,让我们能预处理出 aaa 呢?啊,有的兄弟,有的。

我们设一个新的 DP:sumssum_ssums,表示在 sss 这个状态下 lowbit⁡(s)\operatorname{lowbit}(s)lowbit(s)sss 中的每一个点的距离和,于是我们就可以把这个状态转移方程改进一下:

dps=dps⊕lowbit⁡(s)+sumsdp_s=dp_{s\oplus\operatorname{lowbit}(s)}+sum_sdps=dpslowbit(s)+sums

现在就诞生了一个新的问题:sumssum_ssums 怎么求?

如果直接求,我们会发现时间复杂度来到了 O(2nn)O(2^nn)O(2nn)(外面枚举状态,里面枚举 lowbit⁡(s)\operatorname{lowbit}(s)lowbit(s) 到每个点的距离和),仔细观察容易发现:这个 DP 所需要的循环和上面的 DP 所需要的循环很类似。那我们就采用相同的方法:把动点固定成定点。而 lowbit⁡(s)\operatorname{lowbit}(s)lowbit(s) 已经被用过了,因此我们换个特殊点:最大的点。我们记做 upbit⁡(s)\operatorname{upbit}(s)upbit(s) 吧。

于是我们就可以写出状态转移方程:

sums=sums⊕upbit⁡(s)+glowbit⁡(s),upbit⁡(s)sum_s=sum_{s\oplus\operatorname{upbit}(s)}+g_{\operatorname{lowbit}(s),\operatorname{upbit}(s)}sums=sumsupbit(s)+glowbit(s),upbit(s)

其中 ggg 表示题中输入的那个数组。

然后就可以快乐的写代码了!

我绝对不会告诉你我没写。

T2

考试时:不是 k≤120k\le120k120 是什么鬼!?还有那个 n≤1036n\le10^{36}n1036 是什么!?这是要弄死人的节奏吗!?

为了您能更好的理解这道题是如何被一步一步想出来的,我们一个数据点一个数据点的讲:

Subtask 1

很简单,翻译下来就是 x−y=nx-y=nxy=n,令 y=1y=1y=1,于是 x=n+1x=n+1x=n+1,然后直接输出即可。注意题目中说了 x,y≤1036x,y\le10^{36}x,y1036

Subtask 2

翻译一下就是 x2−y2=(x+y)(x−y)=nx^2-y^2=(x+y)(x-y)=nx2y2=(x+y)(xy)=n,现在设 a=x+y,b=x−ya=x+y,b=x-ya=x+y,b=xy,则 x=a+b2,y=a−b2x=\cfrac{a+b}{2},y=\cfrac{a-b}{2}x=2a+b,y=2ab,变形一下就是 a+b=2x,a−b=2ya+b=2x,a-b=2ya+b=2x,ab=2y,因为 x,y∈Zx,y\isin \Zx,yZ,所以 2x,2y2x,2y2x,2y 都是偶数,因此 a+b,a−ba+b,a-ba+b,ab 都是偶数,而 a+b,a−ba+b,a-ba+b,ab 都是偶数的情况只有两种:

  1. a,ba,ba,b 都是奇数。
  2. a,ba,ba,b 都是 444 的偶数。

a,ba,ba,b 都是奇数时

那么 ab=nab=nab=n 也是一个奇数,这时设 b=1,a=nb=1,a=nb=1,a=n 可知:x=n+12,y=n−12x=\cfrac{n+1}{2},y=\cfrac{n-1}{2}x=2n+1,y=2n1

a,ba,ba,b 都是偶数时

那么 ab=nab=nab=n 就是 444 的倍数,这时设 b=2,a=n2b=2,a=\cfrac{n}{2}b=2,a=2n 可知:x=n2+22,y=n2−22x=\cfrac{\cfrac{n}{2}+2}{2},y=\cfrac{\cfrac{n}{2}-2}{2}x=22n+2,y=22n2

注意:当 n=1n=1n=1n=4n=4n=4 时,不存在两个不同的数 x,yx,yx,y 使得 x2−y2=nx^2-y^2=nx2y2=n

Subtask 3

详见 Cubes。

Subtask 4

显然,x,y≤106x,y\le10^6x,y106,而 xk−ykx^k-y^kxkyk 具有单调性,双指针一下即可。

Subtask 5

显然在送分,当 k≥3k\ge3k3 时,x,y≤10163<108x,y\le10^{\frac{16}{3}}\lt10^8x,y10316<108,直接按照 Subtask 4 暴力即可。

Subtask 6

思考一下 Cubes 的做法,就很容易发现这个点的解法:二分。因为特殊性质中给了 x−y=1x-y=1xy=1,于是 x=y+1x=y+1x=y+1,原式就可以被转化为 (y+1)k−yk=n(y+1)^k-y^k=n(y+1)kyk=n,然后不难证明这个函数是具有单调性的,然后二分 yyy 即可。

正解

在 Subtask 6 的基础上再深挖:首先我们知道这个式子:

xk−yk=(x−y)∑i=0k−1xk−i−1yi=(x−y)(xk−1+xk−2y+xk−3y2⋯+xyk−2+yk−1)x^k-y^k=(x-y)\sum_{i=0}^{k-1}x^{k-i-1}y^i=(x-y)(x^{k-1}+x^{k-2}y+x^{k-3}y^2\dots+xy^{k-2}+y^{k-1})xkyk=(xy)i=0k1xki1yi=(xy)(xk1+xk2y+xk3y2+xyk2+yk1)

而这个式子等于 nnn,即是说:

(x−y)∑i=0k−1xk−i−1yi=n(x-y)\sum_{i=0}^{k-1}x^{k-i-1}y^i=n(xy)i=0k1xki1yi=n

在 Subtask 6 里面说了一个关键信息:x−y=1x-y=1xy=1。那这里我们能不能强制性的让 x−yx-yxy 等于某个数,或者换种方法来说:枚举 x−yx-yxy 等于多少。

我们来思考一下枚举 x−yx-yxy 所需要的时间复杂度是多少。因为 xk−ykx^k-y^kxkyk 是一个 kkk 次式,而 x−yx-yxy 是一个一次式,所以 x−yx-yxy 的次数就是 xk−ykx^k-y^kxkyk1k\frac{1}{k}k1,或者说,是 nnn1k\frac{1}{k}k1

因此我们可知这个式子:x−y≤n1kx-y\le n^{\frac{1}{k}}xynk1

因为题目中有这个条件:n≤min⁡(106k,1036)n\le\min(10^{6k},10^{36})nmin(106k,1036),因此 nnn 再大也大不过 106k10^{6k}106k,所以 n≤106kn\le10^{6k}n106k,所以 x−y≤n1k≤106kk=106x-y\le n^{\frac{1}{k}}\le10^{\frac{6k}{k}}=10^6xynk110k6k=106,诶,可以过!

另一方面:因为 x−yx-yxy 乘上后面那么大一堆东西等于 nnn,所以它还是 nnn 的因数。

确定了 x−yx-yxy,然后就可以二分了。

注意:xk−ykx^k-y^kxkyk 不能直接算,因为有可能 xk>1036,yk>1036x^k\gt10^{36},y^k\gt10^{36}xk>1036,yk>1036,但 xk−yk≤1036x^k-y^k\le10^{36}xkyk1036,因此要先转化成上面那个一大坨式子(因为那个式子是两个数相乘,结果只会变大不会变小),再计算它的值。

还有就是中间计算要时刻关注数的大小是否超出了 103610^{36}1036,反正细节很多,也很难写。

代码:

#include<bits/stdc++.h>
#define int long long
#define _ __int128
#define code using
#define by namespace
#define plh std
code by plh;
by Plh
{_ read(){_ z = 0, f = 1;char c = getchar();while(c < '0'||c > '9'){if(c == '-') f=-1;c = getchar();}while(c >= '0'&&c <= '9'){z = z * 10 + c - '0';c = getchar();}return z * f;}void write(_ x){if(x < 0){putchar('-');x = -x;}int a[46], top = 0;while(x){a[top++] = x % 10;x /= 10;}while(top) putchar(char(a[--top] + '0'));}
}
code by Plh;
const _ INF = (_)(1e18) * (_)(1e18);
_ k, n, c, t;
bool check(_ x, _ y)
{if(INF / x < y) return true;return false;
}
_ mulcheck(_ x, _ y)
{if(INF / x >= y) return x * y;return INF;
}
_ qpow(_ x, _ y)
{_ z = 1;bool fl = false;while(y){if(y & 1){if(fl||check(z, x)) return INF;else z *= x;}if(check(x, x)) fl=true;else x *= x;y >>= 1;}return z;
}
_ up()
{_ l = 1, r = qpow(10, 36 / k + 1), mid;while(l <= r){mid = l + r >> 1;if(qpow(mid, k)>n) r = mid - 1;else l= mid + 1;}return r + 1;
}
_ calc(_ x, _ y, _ z)
{_ xx = 1, yy = 1, sum = 0;for(int i = 1;i < k;i++){if(check(xx, x)) return INF;else xx *= x;}for(int i = 0;i < k;i++){if(mulcheck(xx, yy) == INF) return INF;sum += mulcheck(xx, yy);if(i == k - 1) break;xx /= x;if(check(yy, y)) return INF;else yy *= y;}if(mulcheck(sum, x - y) == INF) return INF;return mulcheck(sum, x - y);
}
void solve()
{k = read(), n = read();if(k == 1){if(n == INF) puts("-1 -1");else write(n + 1), putchar(' '), write(1), putchar('\n');return;}if(k == 2){if(n == 1||n == 4) puts("-1 -1");else if(n & 1) write((n + 1) >> 1), putchar(' '), write((n - 1) >> 1), putchar('\n');else if((n & 3) == 0) write(((n >> 1) + 2) >> 1), putchar(' '), write(((n >> 1) - 2) >> 1), putchar('\n');else puts("-1 -1");return;}_ m = up();for(int i = 1;i <= m;i++){if(n % i) continue;_ l = 1, r = qpow(10, 36 / (k - 1) + 1), mid, t;while(l <= r){mid = l + r >> 1;t = calc(mid + i, mid, k);if(t == n){write(mid + i),putchar(' '), write(mid), putchar('\n');return;}if(t > n) r = mid - 1;else l = mid + 1;}}puts("-1 -1");return;
}
signed main()
{c = read(), t = read();while(t--) solve();return 0;
}

总之,考试时把 k=1k=1k=1k=2k=2k=2 时的情况写出来了,结果因为 INF 的问题直接爆 0(因为我当时是直接写的 INF=1e36,谁知道它会炸掉啊!!!)。

T3

一道典型的 DP。

说句实话:它不告诉我是 DP,我还真看不出来这是道 DP。

一看题:”最多 mmm 个杯,最多操作 www 次“。一看到这句话,贪心、二分、DP 中选一个。

贪心肯定不行,因为你找不到贪心策略。二分肯定不行,因为没有单调性。因此这题是 DP。(好牵强的理由……)

首先定义状态:设 dpi,jdp_{i,j}dpi,j 表示在还剩 iii 个玻璃杯、还可以操作 jjj 的情况下所能测出来的最大楼层,于是就可以写出状态转移方程:

dpi,j=dpi−1,j−1+dpi,j−1+1dp_{i,j}=dp_{i-1,j-1}+dp_{i,j-1}+1dpi,j=dpi1,j1+dpi,j1+1

我解释一下:假设我从第 nownownow 层扔了个玻璃杯,如果玻璃杯没碎,那就还剩 iii 个玻璃杯、j−1j-1j1 次操作,而这样我们也得到了 x>nowx\gt nowx>now 这个结论(xxx 的定义和题目中的一样),说明在 nownownow 层上面最多就有 dpi,j−1dp_{i,j-1}dpi,j1 层。如果玻璃杯碎了,那就还剩 i−1i-1i1 个玻璃杯、j−1j-1j1 次操作,同样我们得到了 x<nowx\lt nowx<now 这个结论,说明在 nownownow 层下面最多有 dpi,j−1dp_{i,j-1}dpi,j1 层,再加上 nownownow 这一层可以得到上述状态转移方程。

图示:

但是请注意数据范围:m≤107,w≤107m\le10^7,w\le10^7m107,w107

现在考虑优化。

仔细观察这个状态转移方程:dpi,j=dpi−1,j−1+dpi,j−1+1dp_{i,j}=dp_{i-1,j-1}+dp_{i,j-1}+1dpi,j=dpi1,j1+dpi,j1+1,你有没有觉得有点眼熟?如果没有,请看这个状态转移方程:

dpi,j=dpi−1,j−1+dpi−1,jdp_{i,j}=dp_{i-1,j-1}+dp_{i-1,j}dpi,j=dpi1,j1+dpi1,j

如果到这个份上你都还没看出来,可以选择回炉重造了。

很明显:杨辉三角啊!

由上可推出:dpi,j=∑k=1iCjkdp_{i,j}=\sum_{k=1}^iC_j^kdpi,j=k=1iCjk,证明太简单,这里就不证了。(我绝对不会告诉你我没看懂证明。)

实在想看证明的同学就看一下题解上的证明:

(至少我没看懂……我觉得他应该就是假设它成立了,然后推出来了这样下去后面都成立,就成立了,原版应该是数学归纳法,但题解作者应该太懒了。)

于是就可以快乐的敲代码了。

注意:题目中要对 998244353998244353998244353 取模,而组合计数中有除数,所以还需要提前求一下阶乘逆元。

代码:

#include<bits/stdc++.h>
#define int long long
#define code using
#define by namespace
#define plh std
code by plh;
const int mod=998244353;
int c,t,m,w,ans,fac[10000006],bfac[10000006];
int qpow(int x,int y)
{if(y==0){return 1;}int t=qpow(x,y>>1);if(y&1){return t*t%mod*x%mod;}else{return t*t%mod;}
}
int C(int x,int y)
{if(x<0||y<0||y<x){return 0;}return fac[y]%mod*bfac[y-x]%mod*bfac[x]%mod;
}
signed main()
{fac[0]=1;for(int i=1;i<=10000000;i++){fac[i]=fac[i-1]*i%mod;}bfac[10000000]=qpow(fac[10000000],mod-2);for(int i=9999999;i>=0;i--){bfac[i]=bfac[i+1]*(i+1)%mod;}cin>>c>>t;while(t--){cin>>m>>w;for(int i=1;i<=m;i++){ans=(ans+C(i,w))%mod;}cout<<ans<<endl;ans=0;}return 0;
}

T4

水题,但阴间实现。

首先一看两个水池能互相合并,猜都猜得到是并查集,因此我用一种极其简单的思路写了一个并查集:首先往这个坑所在的大坑里到水,如果要往外溢,就看往哪溢,然后一直模拟就行了。

代码:

#include<bits/stdc++.h>
#define int long long
#define code using
#define by namespace
#define plh std
#define INF	0x3f3f3f3f3f3f3f3f
code by plh;
const int N = 1e6 + 6;
const int mod = 998244353;
int n, q, h[N], wid[N], siz[N], mx[N], inv[N], fa[N];
int find(int x)
{if(x == fa[x]) return x;return fa[x] = find(fa[x]);
}
bool fill(int x, int &y)
{if((mx[x] * wid[x] - siz[x]) >= y){siz[x] += y;y = 0;return 0;}else{y -= (mx[x] * wid[x] - siz[x]);siz[x] = mx[x] * wid[x];return 1;}
}
void merge(int x, int y)
{if(x > y) swap(x,y);int fx = find(x), fy = find(y);if(fx != fy){fa[fy] = fx;wid[fx] += wid[fy];siz[fx] += siz[fy];h[fx] = h[fy];mx[fx] = min(h[fx - 1], h[fx]);}
}
void solve()
{int ans = 0;cin>>n>>q;for(int i = 1;i < n;i++) cin>>h[i];h[0] = h[n] = INF;for(int i = 1;i <= n;i++) fa[i] = i, wid[i] = 1, mx[i] = min(h[i-1], h[i]), siz[i] = 0;while(q--){int op;cin>>op;if(op == 1){int pos, num;cin>>pos>>num;int now = pos;now = find(now);while(num){
//				cout<<num<<'\n';
//				for(int i = 1;i <= n;i++) cout<<siz[i]<<" ";
//				cout<<'\n';if(!fill(now, num)) break;while(h[now - 1] <= h[now]&&num&&fill(now, num)){
//					for(int i = 1;i <= n;i++) cout<<siz[i]<<" ";
//					cout<<'\n';int left = now - 1;left = find(left);if(fill(left, num)){if(mx[left] == mx[now]) merge(left, now);else now = left;}else break;}while(h[now - 1] > h[now]&&num&&fill(now, num)){int right = now + wid[now];right = find(right);if(fill(right, num)){if(mx[now] == mx[right]) merge(now, right);else now = right;}else break;}}
//			for(int i = 1;i <= n;i++) cout<<siz[i]<<" ";
//			cout<<'\n';}else{int pos;cin>>pos;pos = find(pos);ans ^= (siz[pos] % mod * inv[wid[pos]] % mod);}}cout<<ans<<'\n';
}
signed main()
{inv[0] = inv[1] = 1;for(int i = 2;i < N;i++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;int c, t;cin>>c>>t;while(t--) solve();return 0;
}
/*
0 1
5 7
1 3 4 2
1 1 3
2 2
1 2 8
2 2
1 5 5
2 4
2 5
*/

然后完美的 TLE 了……

原因:仔细一算时间复杂度:O(qnα(n))O(qn\alpha(n))O(qnα(n)),其中这个 α(n)\alpha(n)α(n) 是个常数,但是很明显这个常数极大。因为我是一位一位移的,所以耗时自然很大。

那既然问题出在了移动这里,那我们就用一个数组记录下当前这个水槽能到的最远的水槽在哪。然后这个题就 AC 了……

注意:细节很多,而且代码很难写,注意看注释。

#include<bits/stdc++.h>
#define int long long
#define code using
#define by namespace
#define plh std
#define INF	LONG_LONG_MAX
code by plh;
by fastio
{int read(){int z = 0, f = 1;char c = getchar();while(c < '0'||c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0'&&c <= '9'){z = z * 10 + c - '0';c = getchar();}return z * f;}void write(int x){if(x < 0){putchar('-');x=-x;}int top = 0,a[16];while(x){a[top++] = x % 10;x /= 10;}while(top) putchar(char(a[--top] + '0'));}
}
code by fastio;
const int N = 1e6 + 6;
const int mod = 998244353;
int n, q, pos, num, op, ans, now, tmp, tag, h[N], wid[N], siz[N], mx[N], inv[N], lft[N], rgt[N], fa[N];
int find(int x, int *fa)
{if(x == fa[x]) return x;return fa[x] = find(fa[x], fa);
}
bool cmp(int x, int y)
{if(y == INF) return false;//高度无限,根本填不满x = find(x, fa);return siz[x] >= wid[x] * y;//我的水量是否大于等于最大水量
}
void merge(int x, int y)
{if(x > y) swap(x,y);//以小的为根if(x < 1||x > n||y < 1||y > n) return;//是否满足条件x = find(x, fa), y = find(y, fa);if(x == y||x + wid[x] != y||!wid[x]||!wid[y]) return;//这两个点已经连在一起?两个点不相邻?已经有一个点连到其他连通块中了?if(!cmp(x, h[y - 1])||!cmp(y,h[y - 1])) return;//两边的水还没满了?fa[y] = x, wid[x] += wid[y], siz[x] += siz[y];//合并 if(min(h[x - 1], h[x + wid[x] - 1]) == INF) mx[x] = INF;else mx[x] = min(h[x - 1], h[x + wid[x] - 1]) * wid[x];siz[y] = wid[y] = mx[y] = 0;return;
}
bool fill(int x, int &y)
{x = find(x, fa), tmp = x + wid[x];if(!y||siz[x] == mx[x]) return false;if(mx[x] - siz[x] <= y)//如果倒不完 {y -= mx[x] - siz[x];//先倒 siz[x] = mx[x];merge(x, x - 1);//然后看看左右有没有和自己一样满了的可以合并 merge(x, tmp);}else siz[x] += y, y = 0;//反之直接倒 return y&&siz[x] != mx[x];//如果有水且还能倒就继续倒 
}
void solve()
{ans = 0;n = read(), q = read();for(int i = 1;i < n;i++) h[i] = read();h[0] = h[n] = INF;for(int i = 1;i <= n;i++) lft[i] = rgt[i] = fa[i] = i, wid[i] = 1, mx[i] = min(h[i - 1], h[i]), siz[i] = 0;while(q--){op=read();if(op == 1){pos = read(), num = read();while(num){now = pos;while(fill(now, num));//尽可能的往里面倒水while(cmp(now, h[now - 1])&&num)//倒过了但还有水且我已经倒满了,则先尽可能往左边倒{if(lft[now] == now) lft[now] = now - 1, now--;//如果我都被倒满了但我原本没往左溢,那我现在就可以往左溢了并记录下来我往左溢到了哪else now = find(now, lft);//否则找我可以向左最远可以溢到哪if(now < 1) break;//跑出去了,也就是跑到最左边了while(fill(now, num));//继续在最左边加水}tag = h[now - 1];now = pos;while(fill(now, num));//尽可能的往里面倒水while(cmp(now, h[now])&&!cmp(now, tag)&&num)//倒过了但还有水且我已经倒满了且我最左边的高度比最右边的高度高,则再往右倒{if(rgt[now] == now) rgt[now] = now + 1, now++;//如果我都被倒满了但我原本没往右溢,那我现在就可以往右溢了并记录下来我往右溢到了哪else now = find(now, rgt);//否则找我可以向右最远可以溢到哪if(now > n) break;//跑出去了,也就是跑到最右边了while(fill(now, num));//继续在最右边加水}}}else{pos = read();find(pos, fa);ans ^= (siz[fa[pos]] % mod * inv[wid[fa[pos]]] % mod);}}if(ans == 0) putchar('0');write(ans);putchar('\n');return;
}
signed main()
{inv[0] = inv[1] = 1;for(int i = 2;i <= 1000000;i++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;int c, t;c=read(), t=read();while(t--) solve();return 0;
}
/*
0 1
5 7
1 3 4 2
1 1 3
2 2
1 2 8
2 2
1 5 5
2 4
2 5
*/

总结

  • T1:打卡题,很容易想到正解。
  • T2:简单题,但阴间实现,而且代码很难写,细节特别多。
  • T3:有难度,主要是完全看不出来是个 DP,还有就是结论很难想到。
  • T4:简单题,但阴间实现,代码难写,细节多。

上周考的题,到昨天才改完,代码实在是太难写了,还希望各位能点个赞,谢谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90230.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90230.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

旋转屏幕优化

1.问题背景 从google原生算法&#xff0c;可以知道其有2个比较大的缺陷&#xff1a; 1) 通过重力传感器传来的x&#xff0c;y&#xff0c;z轴的加速度合成之后只有一个垂直往下的加速度&#xff0c;如果此时用户在别的方向上有加速度&#xff0c;那么通过反余弦、反正切等计算…

Java---day2

七、IDEA开发工具 &#x1f4e6; 一、下载 IntelliJ IDEA 官网地址&#xff1a; &#x1f517; IntelliJ IDEA – the IDE for Pro Java and Kotlin Development 版本选择&#xff1a; 版本说明Community Edition (CE)免费开源版本&#xff0c;适合 Java、Kotlin、Android…

RAL-2025 | 清华大学数字孪生驱动的机器人视觉导航!VR-Robo:面向视觉机器人导航与运动的现实-模拟-现实框架

作者&#xff1a; Shaoting Zhu, Linzhan Mou, Derun Li, Baijun Ye, Runhan Huang, Hang Zhao单位&#xff1a;清华大学交叉信息研究院&#xff0c;上海期智研究院&#xff0c;Galaxea AI&#xff0c;上海交通大学电子信息与电气工程学院论文标题&#xff1a;VR-Robo: A Real-…

碰一碰发视频 + 矩阵系统聚合平台源码搭建,支持OEM

随着短视频生态与多平台运营需求的融合&#xff0c;“碰一碰发视频 矩阵系统” 聚合平台成为内容创作者与企业营销的新基建。这类系统需实现近场交互触发、多平台内容分发、数据聚合分析的全流程闭环&#xff0c;其源码搭建与定制开发需突破硬件交互与软件矩阵的技术壁垒。核心…

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级

1. 缓存雪崩&#xff08;Cache Avalanche&#xff09;定义&#xff1a;缓存雪崩是指大量缓存中的数据在同一时间过期&#xff0c;导致大量请求同时访问数据库&#xff0c;造成数据库压力骤增&#xff0c;甚至可能导致数据库崩溃。原因&#xff1a;多个缓存的 key 在同一时间过期…

【unity实战】Unity手搓脚本工具实现合并网格功能

注意:考虑到实战的内容比较多,我将该内容分开,并全部整合放在【unity实战】专栏里,感兴趣的小伙伴可以前往逐一查看学习。 文章目录 前言实战1、简单的合并网格实现2、设置统一的材质3、设置不同的多种材质4、多材质网格合并方案专栏推荐完结前言 有许多单独的网格对象会影…

ThreadPoolTaskExecutor 的使用案例

ThreadPoolTaskExecutor 的使用案例 1. 依赖说明 <!-- Spring Retry&#xff08;用于任务重试&#xff09; --> <dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.1<…

0.3mg硝酸甘油舌下片:冠心病预防中的“消防员”

冠状动脉疾病&#xff08;CAD&#xff09;如同一颗定时炸弹&#xff0c;即使在成功进行血运重建或药物治疗后&#xff0c;心绞痛急性发作的风险依然如影随形。在冠心病管理的漫长战役中&#xff0c;二级预防的核心目标不仅仅是延缓疾病进展&#xff0c;更是预防致命性心脏事件复…

【Spring源码学习系列】基础架构和环境搭建

一直以来都把精力花在中间件的研究和系统设计上&#xff0c;忽略了离我最近的spring&#xff0c;最近开始学习spring的源码了&#xff0c;为了学习到成体系的spring知识和提高学习效率&#xff0c;想要找了一本书看&#xff0c;最终选的是郝佳的《Spring源码深度解析&#xff0…

C++十大排序详解(包括变种优化)

排序**基础排序算法**1. **冒泡排序&#xff08;Bubble Sort&#xff09;**冒泡排序优化**1. 提前终止优化&#xff08;标志位优化&#xff09;****原理**&#xff1a;**实现示例**&#xff08;以C为例&#xff09;&#xff1a;**优点**&#xff1a;**2. 双向冒泡排序&#xff…

React 性能优化实战:用useTransition解决卡顿问题

文章目录1. 概述2. 基本原理与语法3. 应用场景3.1 数据密集型界面的更新优化3.2 动态内容切换的平滑过渡3.3 搜索与过滤结果的实时展示4. 与其他相关Hook的对比5. 结合Suspense使用6. 注意事项1. 概述 useTransition Hook 。它允许开发者将一些非紧急的 UI 更新标记为 “过渡更…

基于Rust红岩题材游戏、汽车控制系统、机器人运动学游戏实例

根据红岩题材设计的关键游戏实例 以下是根据红岩题材设计的关键游戏实例,结合Rust语言特性(如安全并发、ECS架构等)的框架性方案。所有设计均需符合Rust语法规范,实际开发需配合游戏引擎(如Bevy、Amethyst)。 核心系统模块 // ECS架构示例(Bevy引擎) use bevy::prel…

【ZYNQ Linux开发】BRAM的几种驱动方式

1 Vivado配置 ​ BRAM 的使用方法为使用 AXI BRAM 控制器来控制 BRAM 生成器&#xff0c;Block Design 连接如下&#xff1a; 我这里配置的是真双端口 RAM&#xff0c;通过 PL 的逻辑对 BRAM 生成器的端口 B 进行写操作&#xff0c;在 PS 端对端口 A 进行读。 BRAM 控制…

Flink ClickHouse 连接器数据写入源码深度解析

一、引言 在大数据处理的实际应用场景中&#xff0c;数据的高效存储与处理至关重要。Flink 作为一款强大的流式计算框架&#xff0c;能够对海量数据进行实时处理&#xff1b;而 ClickHouse 作为高性能的列式数据库&#xff0c;擅长处理大规模数据分析任务。Flink ClickHouse 连…

OpenCV 人脸分析------面部关键点检测类cv::face::FacemarkLBF

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用 Local Binary Features (LBF) 算法进行面部关键点检测&#xff08;facial landmark detection&#xff09;。该算法通过级联回归树预测人脸的…

Netstat高级分析工具:Windows与Linux双系统兼容的精准筛查利器

Netstat高级分析工具&#xff1a;Windows与Linux双系统兼容的精准筛查利器在网络安全运维中&#xff0c;快速识别可疑连接是防御入侵的关键一步。本文将介绍一款我本人开发的原创高效的双系统兼容Netstat信息分析工具&#xff0c;大幅提升恶意连接筛查效率。一、Netstat分析在安…

Bright Data MCP+Trae :快速构建电商导购助手垂直智能体

声明&#xff1a;本测试报告系作者基于个人兴趣及使用场景开展的非专业测评&#xff0c;测试过程中所涉及的方法、数据及结论均为个人观点&#xff0c;不代表任何官方立场或行业标准。 文章目录 一、引言1.1 当前AI智能体的趋势1.2 构建智能体面临的最大挑战&#xff1a;数据来…

plantuml用法总结

时序图 参考 https://blog.csdn.net/vitaviva/article/details/120735745用PlantUML简化复杂时序图的秘诀 startuml skin rose actor User as user participant "Component A" as A participant "Component B" as Buser -> A: Request data activate …

基于自研心电芯片国产化手持单导/6导/12导心电解决方案

苏州唯理作为国内心电芯片国产化厂商&#xff0c;面向家用场景&#xff0c;推出了国产化的手持单导/6导/12导心电仪技术解决方案&#xff0c;可以让家用心电图仪成本可控&#xff0c;信号链路质量更佳稳定。该方案已在多家客户中实现批量出货。唯理科技同样提供了医疗级的心电图…

Sass详解:功能特性、常用方法与最佳实践

Sass详解&#xff1a;功能特性、常用方法与最佳实践 Sass&#xff08;Syntactically Awesome Style Sheets&#xff09;作为CSS预处理器领域的先驱&#xff0c;自2006年由Hampton Catlin创建以来&#xff0c;已成为现代前端开发中不可或缺的工具。它通过引入变量、嵌套、混合宏…