普及模拟3
普及模拟3

\(T1\) 最大生成树 \(100pts\)
- 简化题意:给定一个 \(n(1 \le n \le 1 \times 10^5)\) 个点的完全图,给定各点的点权 \(a_i(1 \le i \le n)\) ,两点间的边权为 \(|a_i-a_j|\) ,求该图的最大生成树。
- 正解:贪心,考虑到一个点对答案产生的贡献为 \(\max(a_i-\min\limits_{j=1}^{n} \{ a_j \},\max\limits_{j=1}^{n} \{ a_j \}-a_i)\) ,又因为是完全图,易证得连边后一定是符合题意的解。
ll a[100001];//十年OI一场空,不开long long见祖宗 int main() { ll n,i,ans=0; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } sort(a+1,a+1+n); for(i=1;i<=n-1;i++)//只需要n-1条边 { ans+=max(a[n]-a[i],a[i]-a[1]); } cout<<ans<<endl; return 0; } - 貌似是首A。

\(T2\) 红黑树 \(80pts\)
- 简化题意:给定一棵 \(n(1 \le n \le 1 \times 10^5)\) 个点的有根树, \(1\) 为根节点,初始每个点都是红色,有 \(n\) 次操作,每次操作会把 \(p_i\) 变成黑色,保证操作序列 \(p\) 是一个排列,即每次操作的点都不相同。每次操作完成后,你需要输出有多少个子树是红黑子树,即子树内既包含黑点又包含红点。
- 本题中的红黑树与 红黑树 无任何关系。
- 部分分:
- \(20pts\) :对链的情况特判。
- \(80pts\)(在线做法) :一遍 \(DFS\) 处理出以 \(i(1 \le i \le n)\) 为根的子树大小,每次修改暴力跳父亲直到根节点,卡在了链的测试点上,复杂度为 \(O(n^2)\) 。
struct node { int nxt,to; }e[200001]; int head[200001],siz[200001],fa[200001],vis[200001],cnt=0; void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(int x,int father) { fa[x]=father; for(int i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=father) { dfs(e[i].to,x); siz[x]+=siz[e[i].to]+1; } } } int main() { int n,i,j,u,v,p,ans=0; cin>>n; for(i=1;i<=n-1;i++) { cin>>u; v=i+1; add(u,v); } dfs(1,0); for(i=1;i<=n;i++) { siz[i]++; } for(i=1;i<=n;i++) { cin>>p; for(j=p;j!=0;j=fa[j]) { siz[j]--; if(vis[j]==0) { if(1<=siz[j]) { vis[j]=1; ans++; } } else { if(!(1<=siz[j])) { vis[j]=0; ans--; } } } cout<<ans<<" "; } return 0; }
- 正解(离线做法):
- 前置知识:红黑子树的产生与消失都是由改变颜色的这个点造成的。
- 例如,把节点 \(x\) 变成黑色后,对于所有包含 \(x\) 的子树 \(T\) ,如果 \(x\) 是该子树内第一个变成黑色的点,那么 \(x\) 会让 \(T\) 变成红黑子树;如果 \(x\) 是该子树内最后一个红色的点,那么 \(x\) 会让 \(T\) 变成非红黑子树。
- 记录下这棵子树中黑点最先出现和最后一个红点变成黑点的时候。
- 做法一:暴力跳父亲时跳到某个点时,若这个点既不是以这个点的父亲节点为根的子树内最先出现的黑点,也不是最后一个变成黑点的红点时就没有必要跳了,因为不会对答案产生贡献了(这里可能有些绕口,自己可以画图模拟一下)。
- 复杂度貌似很神奇,官方题解写的是 \(O(n)\) 。
struct node { int nxt,to; }e[200001]; int head[200001],minn[200001],maxx[200001],p[200001],id[200001],fa[200001],cnt=0;//minn表示(····)最早出现,maxx表示最后一个(····)消失 void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(int x) { minn[x]=maxx[x]=id[x]; for(int i=head[x];i!=0;i=e[i].nxt) { dfs(e[i].to); minn[x]=min(minn[x],minn[e[i].to]); maxx[x]=max(maxx[x],maxx[e[i].to]); } } int main() { int n,i,j,u,v,ans=0,flag; cin>>n; for(i=1;i<=n-1;i++) { cin>>u; v=i+1; fa[v]=u; add(u,v); } for(i=1;i<=n;i++) { cin>>p[i]; id[p[i]]=i; } dfs(1); for(i=1;i<=n;i++) { for(j=p[i];j!=0;j=fa[j])//暴力跳父亲 { flag=0; if(minn[j]==id[p[i]]) { ans++; flag=1; } if(maxx[j]==id[p[i]]) { ans--; flag=1; } if(flag==0) { break; } } cout<<ans<<" "; } return 0; }
- 复杂度貌似很神奇,官方题解写的是 \(O(n)\) 。
- 做法二:进行差分维护一下。————隔壁 @xrlong 的做法
- 树状数组的区间修改单点查询操作
struct node { int nxt,to; }e[200001]; int head[200001],minn[200001],maxx[200001],p[200001],id[200001],c[400001],cnt=0; int lowbit(int x) { return (x&(-x)); } void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(int x) { minn[x]=maxx[x]=id[x]; for(int i=head[x];i!=0;i=e[i].nxt) { dfs(e[i].to); minn[x]=min(minn[x],minn[e[i].to]); maxx[x]=max(maxx[x],maxx[e[i].to]); } } void update(int n,int x,int key) { for(int i=x;i<=n;i+=lowbit(i)) { c[i]+=key; } } int getsum(int x) { int ans=0; for(int i=x;i>0;i-=lowbit(i)) { ans+=c[i]; } return ans; } int main() { int n,i,j,u,v,ans=0,flag; cin>>n; for(i=1;i<=n-1;i++) { cin>>u; v=i+1; add(u,v); } for(i=1;i<=n;i++) { cin>>p[i]; id[p[i]]=i; } dfs(1); for(i=1;i<=n;i++) { update(n,minn[i],1); update(n,maxx[i]-1+1,-1); } for(i=1;i<=n;i++) { cout<<getsum(i)<<" "; } return 0; } - 差分
struct node { int nxt,to; }e[200001]; int head[200001],minn[200001],maxx[200001],p[200001],id[200001],sum[400001],cnt=0; void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(int x) { minn[x]=maxx[x]=id[x]; for(int i=head[x];i!=0;i=e[i].nxt) { dfs(e[i].to); minn[x]=min(minn[x],minn[e[i].to]); maxx[x]=max(maxx[x],maxx[e[i].to]); } } int main() { int n,i,j,u,v,ans=0; cin>>n; for(i=1;i<=n-1;i++) { cin>>u; v=i+1; add(u,v); } for(i=1;i<=n;i++) { cin>>p[i]; id[p[i]]=i; } dfs(1); for(i=1;i<=n;i++) { sum[minn[i]]++; sum[maxx[i]-1+1]--; } for(i=1;i<=n-1;i++) { ans+=sum[i]; cout<<ans<<" "; } cout<<"0"; return 0; }
- 树状数组的区间修改单点查询操作
- 做法一:暴力跳父亲时跳到某个点时,若这个点既不是以这个点的父亲节点为根的子树内最先出现的黑点,也不是最后一个变成黑点的红点时就没有必要跳了,因为不会对答案产生贡献了(这里可能有些绕口,自己可以画图模拟一下)。
- 前置知识:红黑子树的产生与消失都是由改变颜色的这个点造成的。
\(T3\) 校门外的树 \(30pts\)
- 简化题意:门外有 \(n\) 棵树,每棵树有一个初始高度 \(h_i\) 和生长速度 \(v_i\) ,在接下来的 \(m\) 天中,第 \(i\) 棵树会长高 \(v_i\) ,之后有两种事件可能会发生,操作如下(对 \(2^{64}\) 取模):
- 操作一:将 \([l,r]\) 内树的生长速度 \(v_i(l \le i \le r)\) 增加 \(v\) 。
- 操作二:求 \(\sum\limits_{i=l}^{r} h_i\) 。
- 部分分:
- \(30pts\) : \(n^2\) 暴力枚举。
- \((30+20=50)pts\) :考虑到没有修改操作,维护一下即可。
- 正解:
-
简化版:若一个数 \(a\) ,有它的增长量 \(v\) ,在第 \(i\) 次操作时,有 \(a_{i}=a_{i-1}+v=a_1+i \times v\) 。
-
对 \(2^{64}\) 取模直接用 \(unsigned \ long \ long\) 自然溢出即可。
-
令 \(a_{i,j}\) 表示第 \(i\) 棵树第\(j\) 天的高度,特别地,有 \(a_{i,0}=h_i\) ,接着进行前缀和优化 \(sum_i=\sum\limits_{j=1}^{i} a_{j,0}(1 \le i,j \le n)\) 。
-
将操作二式子进行化简,有
\(\begin{aligned}\sum\limits_{i=l}^{r} a_{i,k} \end{aligned}\)
\(\begin{aligned} &=\sum\limits_{i=l}^{r} a_{i,0} \times k \times \sum\limits_{i=l}^{r} v_{i,num_i}-\sum\limits_{i=l}^{r}\sum\limits_{j=1}^{num_i}v_{i,j} \times day_{i,j} \end{aligned}\)
\(\begin{aligned} &= sum[r]-sum[l-1]+k \times \sum\limits_{i=l}^{r} v_{i,num_i}-\sum\limits_{i=l}^{r}\sum\limits_{j=1}^{num_i-1}(v_{i,j+1}-v_{i,j}) \times day_{i,j}\end{aligned}\) ,
其中 \(day_{i,j}\) 表示第 \(i\) 棵树第 \(j\) 次修改速度时是第几天,\(num_i\) 表示第 \(i\) 棵树生长速度修改的次数, \(k\) 表示本次是第 \(k\) 次操作。
-
考虑用线段树维护 \(\sum\limits_{i=l}^{r} v_{i,num_i}\) 和 \(\sum\limits_{i=l}^{r}\sum\limits_{j=1}^{num_i-1}(v_{i,j+1}-v_{i,j}) \times day_{i,j}\) ,将其 分别储存在两棵线段树 或存在一棵线段树中(其实差别不大)。
ull h[3000000],v[3000000],sum[3000000]; struct SegmentTree { ull l,r,sum[2],lazy[2]; }tree[3000000]; ull lson(ull x) { return x*2; } ull rson(ull x) { return x*2+1; } void pushup(ull rt,ull pd) { tree[rt].sum[pd]=tree[lson(rt)].sum[pd]+tree[rson(rt)].sum[pd]; } void build(ull rt,ull l,ull r,ull pd) { tree[rt].l=l; tree[rt].r=r; tree[rt].lazy[pd]=0; if(l==r) { tree[rt].sum[pd]=v[l]; return; } ull mid=(l+r)/2; build(lson(rt),l,mid,pd); build(rson(rt),mid+1,r,pd); pushup(rt,pd); } void pushdown(ull rt,ull pd) { if(tree[rt].lazy[pd]!=0) { tree[lson(rt)].lazy[pd]+=tree[rt].lazy[pd]; tree[rson(rt)].lazy[pd]+=tree[rt].lazy[pd]; tree[lson(rt)].sum[pd]+=tree[rt].lazy[pd]*(tree[lson(rt)].r-tree[lson(rt)].l+1); tree[rson(rt)].sum[pd]+=tree[rt].lazy[pd]*(tree[rson(rt)].r-tree[rson(rt)].l+1); tree[rt].lazy[pd]=0; } } void update(ull rt,ull l,ull r,ull val,ull pd) { if(l<=tree[rt].r&&tree[rt].l<=r) { if(l<=tree[rt].l&&tree[rt].r<=r) { tree[rt].lazy[pd]+=val; tree[rt].sum[pd]+=val*(tree[rt].r-tree[rt].l+1); return; } pushdown(rt,pd); update(lson(rt),l,r,val,pd); update(rson(rt),l,r,val,pd); pushup(rt,pd); } } ull query(ull rt,ull l,ull r,ull pd) { if(r<tree[rt].l||tree[rt].r<l) { return 0; } if(l<=tree[rt].l&&tree[rt].r<=r) { return tree[rt].sum[pd]; } pushdown(rt,pd); return query(lson(rt),l,r,pd)+query(rson(rt),l,r,pd); } int main() { ull n,m,i,pd,l,r,v2; cin>>n>>m; for(i=1;i<=n;i++) { cin>>h[i]>>v[i]; sum[i]=sum[i-1]+h[i]; } build(1,1,n,0); for(i=1;i<=m;i++) { cin>>pd>>l>>r; if(pd==1) { cin>>v2; update(1,l,r,v2,0); update(1,l,r,v2*i,1); } if(pd==2) { cout<<(sum[r]-sum[l-1])+i*query(1,l,r,0)-query(1,l,r,1)<<endl; } } return 0; }-
隔壁有口胡李超线段树的做法,不是很懂。


-
还有口胡吉司机线段树的。

-
\(T4\) 种树 \(0pts\)
- 简化题意:约翰要带 \(n\) 只牛去参加 \(q\) 次集会里的展示活动(每次集会是相互独立的),这些牛可以是公牛,也可以是母牛。牛们要站成一排,但是公牛是好斗的,为了避免公牛闹出乱子,约翰决定第 \(i(1 \le i \le q)\) 次集会中第 \(x_i\) 头必须是母牛,且任意两只公牛之间至少要有 \(k_i-1\) 只母牛。请计算一共有多少种排队的方法,所有公牛可以看成是相同的,所有母牛也一样。答案对 \(998244353\) 取模。
- 弱化版:luogu P6191 Bulls And Cows S
- @xrlong 说和之前的 luogu T309085 [DILL AKOI R3 G] 风头 很像。
- 部分分:
- \(0pts\) :当 \(k=1\) 时,易知方案数为 \(2^{n-1}\) 。
- \(60pts\) :计数类型的 \(DP\) 。
- 对于第 \(j(1 \le j \le q)\) 次集会,令 \(f_i(0 \le i \le n)\) 表示第 \(i\) 头是母牛的方案数, \(g_i(0 \le i \le n)\) 表示第 \(i\) 头是公牛的方案数。由定义,有 \(f_0=g_0=0,f_1=1,g_1=\begin{cases}1 & x \ne 1 \\ 0 & x=1\end{cases}\) 。容易对于 \(2 \le i \le n\) ,有递推式 \(f_i=f_{i-1}+g_{i-1},g_i=\begin{cases}0 & x=i \\ 1 & x \ne i,i \le k \\ f_{i-k}+g_{i-k} & x \ne i,i>k \end{cases}\) 。
- \(f_n+g_n\) 即为所求。
- 单次时间复杂度为 \(O(n)\) 。
- \(hack\) 数据生成器如下。
int main() { srand(time(0)); cout<<100000<<" "<<100000<<endl; for(int i=1;i<=100000;i++) { cout<<(rand()%100000+1)<<" "<<i<<endl; } }
ll f[100001],g[100001]; int main() { ll n,q,i,j,x,k; cin>>n>>q; for(i=1;i<=q;i++) { cin>>x>>k; f[1]=1; if(x!=1) { g[1]=1; } else { g[1]=0; } for(j=2;j<=n;j++) { f[j]=(f[j-1]+g[j-1])%998244353; if(j==x) { g[j]=0; } else { if(j<=k) { g[j]=1; } else { g[j]=(f[j-k]+g[j-k])%998244353; } } } cout<<(f[n]+g[n])%998244353<<endl; } return 0; } - \(hack\) 数据生成器如下。
- \(100pts\) :组合。
- 依据容斥原理,有第 \(x\) 头是母牛的方案数 \(=\) 总方案数 \(-\) 第 \(x\) 头是公牛的方案数。
- 总方案数:设公牛有 \(j(0 \le i \le n)\) 头,
- 当 \(j=0\) 时,显然只有 \(1\) 种方案。
- 当 \(j \ne 0\) 时,需要固定 \((j-1)(k-1)\) 头母牛,等价于求 \(\sum\limits_{i=1}^{j+1}x_i=n-j-(j-1)(k-1)\) 的非负正整数解的数量,易知其数量为 \(\dbinom{n-j-(j-1)(k-1)+j+1-1}{j+1-1}\) 。
- 第 \(x\) 头是公牛的方案数:
- 第 \(x\) 头是公牛需要 \(x-k+1 \sim x-1,x+1 \sim x+k-1\) 是母牛。
- \(1 \sim x-k\) 的方案数:设公牛有 \(j(0 \le j \le x-k)\) 头,
- 当 \(j=0\) 时,显然只有 \(1\) 种方案。
- 当 \(j \ne 0\) 时,需要固定 \((j-1)(k-1)\) 头母牛,等价于求 \(\sum\limits_{i=1}^{j+1}x_i=x-k-j-(j-1)(k-1)\) 的非负正整数解的数量,易知其数量为 \(\dbinom{x-k-j-(j-1)(k-1)+j+1-1}{j+1-1}\) 。
- \(x+k \sim n\) 的方案数:设公牛有 \(j(0 \le j \le n-(x+k-1))\) 头,
- 当 \(j=0\) 时,显然只有 \(1\) 种方案。
- 当 \(j \ne 0\) 时,需要固定 \((j-1)(k-1)\) 头母牛,等价于求 \(\sum\limits_{i=1}^{j+1}x_i=n-(x+k-1)-j-(j-1)(k-1)\) 的非负正整数解的数量,易知其数量为 \(\dbinom{n-(x+k-1)-j-(j-1)(k-1)+j+1-1}{j+1-1}\) 。
- 总方案数:设公牛有 \(j(0 \le i \le n)\) 头,
- 求一下边界, \(\sum\limits_{j=0}^{\left\lfloor\dfrac{n+k-1}{k-1}\right\rfloor}\dbinom{n-j-(j-1)(k-1)+j+1-1}{j+1-1}-(\sum\limits_{j=0}^{\left\lfloor\dfrac{x-k+k-1}{k-1}\right\rfloor}\dbinom{x-k-j-(j-1)(k-1)+j+1-1}{j+1-1} \times \sum\limits_{j=0}^{\left\lfloor\dfrac{n-(x+k-1)+k-1}{k-1}\right\rfloor}\dbinom{n-(x+k-1)-j-(j-1)(k-1)+j+1-1}{j+1-1})\) 即为所求。
- 预处理时间复杂度为 \(O(n)\) ,单次时间复杂度为 \(O(\dfrac{n}{k})\) 。
- 学校数据太水了,导致此做法过了。
- 极限数据为 \(\dfrac{\dfrac{100000 \times (100000+1)}{2}}{2}\), \(hack\) 数据生成器如下。
int main() { cout<<100000<<" "<<100000<<endl; for(int i=1;i<=100000;++i) { cout<<i<<" "<<2<<endl; } }
- 极限数据为 \(\dfrac{\dfrac{100000 \times (100000+1)}{2}}{2}\), \(hack\) 数据生成器如下。
ll jc[200001],inv[200001],jc_inv[200001]; ll C(ll n,ll m,ll p) { if(n>=m&&n>=0&&m>=0) { return (jc[n]*jc_inv[m]%p)*jc_inv[n-m]%p; } else { return 0; } } ll qpow(ll a,ll b,ll p) { ll ans=1; while(b>0) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } int main() { ll n,q,i,j,x,k,p=998244353,sum1,sum2,sum3; cin>>n>>q; inv[1]=1; jc[0]=jc_inv[0]=jc[1]=jc_inv[1]=1; for(i=2;i<=n;i++) { inv[i]=(p-p/i)*inv[p%i]%p; jc[i]=jc[i-1]*i%p; jc_inv[i]=jc_inv[i-1]*inv[i]%p; } for(i=1;i<=q;i++) { cin>>x>>k; if(k==1) { cout<<qpow(2,n-1,p)<<endl; } else { sum1=sum2=sum3=1; for(j=1;j<=(n+k-1)/(k-1);j++) { sum1=(sum1+C(n-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p; } for(j=1;j<=(x-k+k-1)/(k-1);j++) { sum2=(sum2+C(x-k-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p; } for(j=1;j<=(n-(x+k-1)+k-1)/(k-1);j++) { sum3=(sum3+C(n-(x+k-1)-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p; } cout<<(sum1-sum2*sum3%p+p)%p<<endl; } } return 0; } - 学校数据太水了,导致此做法过了。
- 依据容斥原理,有第 \(x\) 头是母牛的方案数 \(=\) 总方案数 \(-\) 第 \(x\) 头是公牛的方案数。
- 正解
- 根号分治
-
@wkh2008 瑞平 \(T4\) :

-
当 \(k> \sqrt{n}\) 时,考虑到组合做法难以进行进一步预处理,故使用组合做法。
-
当 \(k \le \sqrt{n}\) 时,考虑到对计数类型的 \(DP\) 做法利用容斥原理进一步预处理。对于第 \(j(1 \le j \le q)\) 次集会,令 \(f_i(0 \le i \le n)\) 表示第 \(i\) 头是母牛的方案数, \(g_i(0 \le i \le n)\) 表示第 \(i\) 头是公牛的方案数。由定义,有 \(f_{0,k}=g_{0,k}=0,f_{1,k}=g_{1,k}=1\) 。容易对于 \(2 \le i \le n\) ,有递推式 \(f_{i,k}=f_{i-1,k}+g_{i-1,k},g_{i,k}=\begin{cases} 1 & i \le k \\ f_{i-k,k}+g_{i-k,k} & i>k \end{cases}\) 。最终, \(f_{n,k}+g_{n,k}-(f_{\max(x-k,0),k}+g_{\max(x-k,0),k}) \times (f_{\max(n-(x+k-1),0),k}+g_{\max(n-(x+k-1),0),k})\) 即为所求。
- 本质上是对重复出现的 \(k\) 进行预处理。
-
空间复杂度为 \(O(n \sqrt{n})\) ;预处理时间复杂度为 \(O(n \sqrt{n})\) ,单次查询时间复杂度为 \(O(\sqrt{n})\) 。
ll jc[100001],inv[100001],jc_inv[100001],f[100001][320],g[100001][20],vis[20]; ll C(ll n,ll m,ll p) { if(n>=m&&n>=0&&m>=0) { return (jc[n]*jc_inv[m]%p)*jc_inv[n-m]%p; } else { return 0; } } int main() { ll n,q,i,j,x,k,p=998244353,sum1,sum2,sum3; cin>>n>>q; inv[1]=1; jc[0]=jc_inv[0]=jc[1]=jc_inv[1]=1; for(i=2;i<=n;i++) { inv[i]=(p-p/i)*inv[p%i]%p; jc[i]=jc[i-1]*i%p; jc_inv[i]=jc_inv[i-1]*inv[i]%p; } for(i=1;i<=q;i++) { cin>>x>>k; if(k<=20) { if(vis[k]==0) { vis[k]=1; f[1][k]=g[1][k]=1; for(j=2;j<=n;j++) { f[j][k]=(f[j-1][k]+g[j-1][k])%p; if(j<=k) { g[j][k]=1; } else { g[j][k]=(f[j-k][k]+g[j-k][k])%p; } } } sum1=(f[n][k]+g[n][k])%p; sum2=(f[max(x-k,0ll)][k]+g[max(x-k,0ll)][k])%p; sum3=(f[max(n-(x+k-1),0ll)][k]+g[max(n-(x+k-1),0ll)][k])%p; } else { sum1=sum2=sum3=1; for(j=1;j<=(n+k-1)/(k-1);j++) { sum1=(sum1+C(n-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p; } for(j=1;j<=(x-k+k-1)/(k-1);j++) { sum2=(sum2+C(x-k-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p; } for(j=1;j<=(n-(x+k-1)+k-1)/(k-1);j++) { sum3=(sum3+C(n-(x+k-1)-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p; } } cout<<(sum1-max(sum2,1ll)*max(sum3,1ll)%p+p)%p<<endl; } return 0; }
-
- 根号分治
总结
- \(T1,T3,T4\) 打到 \(8:30,9:30\) 打完 \(T2\) 后就去打高斯消元了,导致没有看见 \(T3\) 的对 \(2^{64}\) 取模(打成了 \(2^{60}\) ),挂了 \(30pts\) 。
- \(T3\) 觉得线段树可做,但不想打了。
- \(T4\) 没有再多想想,没骗到计数类型的 \(DP\) 分。推式子的时候应注意更加模块化,防止因为推式子多推一步而导致无法得到正确式子。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/17648463.html,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。

浙公网安备 33010602011771号