2025多校冲刺省选模拟赛15
\(T1\) A. 小 F 的疑惑
- 原题: TopCoder 12584 SemiPerfectPower
- 等省选后再来改。
\(T2_{1}\) B. 城市规划
-
原题: TopCoder 13518 CityRebuild
-
详见 2025省选模拟8 T1 HZTG5836. 小幸运 。
-
数据中提到了可能会有重复的点,但一些 Corner Case 还是没卡。
-
需要借助
inline
和#pragma GCC optimize(3)
的力量。点击查看代码
#pragma GCC optimize(3) const ll dx[4][3]={{1,0,0},{1,0,0},{-1,0,0},{-1,0,0}},dy[4][3]={{0,-1,0},{0,1,0},{0,-1,0},{0,1,0}}; ll dfn[1610],low[1610],ins[1610],col[1610],x[2][3],y[2][3],tot,scc_cnt,n,w,h; pair<ll,ll>a[1610],z[2][3]; stack<ll>s; vector<ll>e[1610]; inline void add(ll u,ll v) {e[u].push_back(v); } inline void tarjan(ll x) {tot++; dfn[x]=low[x]=tot;ins[x]=1; s.push(x);for(ll i=0;i<e[x].size();i++){if(dfn[e[x][i]]==0){tarjan(e[x][i]);low[x]=min(low[x],low[e[x][i]]);}else{if(ins[e[x][i]]==1){low[x]=min(low[x],dfn[e[x][i]]);}}}if(dfn[x]==low[x]){scc_cnt++;ll tmp=0;while(x!=tmp){tmp=s.top();ins[tmp]=0;col[tmp]=scc_cnt;s.pop();}} } inline bool out_of_bounds(ll x,ll y,ll op,ll mid) {for(ll i=0;i<=1;i++){if(x+dx[op][i]*mid<0||x+dx[op][i]*mid>w||y+dy[op][i]*mid<0||y+dy[op][i]*mid>h) return true;}return false; } inline bool line_cross(ll x1,ll y1,ll x2,ll y2,ll _x1,ll _y1,ll _x2,ll _y2) {if(x1==x2&&_x1==_x2) {return ((x1==_x1)&&((min(y1,y2)<_y1&&_y1<max(y1,y2))||(min(y1,y2)<_y2&&_y2<max(y1,y2))));} if(_x1==_x2){swap(x1,_x1); swap(y1,_y1);swap(x2,_x2); swap(y2,_y2);}if(x1==x2){double _k=1.0*(_y2-_y1)/(_x2-_x1),_b=_y1-_x1*_k,y=_k*x1+_b;return (_x1<x1&&x1<_x2&&min(y1,y2)<y&&y<max(y1,y2));}double k=1.0*(y2-y1)/(x2-x1),b=y1-x1*k,_k=1.0*(_y2-_y1)/(_x2-_x1),_b=_y1-_x1*_k;if(k==_k) return false;double x=(_b-b)/(k-_k);return (min(x1,x2)<x&&x<max(x1,x2)&&min(_x1,_x2)<x&&x<max(_x1,_x2)); } inline bool triangle_cross(ll x1,ll y1,ll op1,ll x2,ll y2,ll op2,ll mid) {for(ll i=0;i<=2;i++) {x[0][i]=x1+dx[op1][i]*mid; y[0][i]=y1+dy[op1][i]*mid;x[1][i]=x2+dx[op2][i]*mid; y[1][i]=y2+dy[op2][i]*mid;}for(ll i=0;i<=2;i++){for(ll j=0;j<=2;j++){if(line_cross(x[0][i],y[0][i],x[0][(i+1)%3],y[0][(i+1)%3],x[1][j],y[1][j],x[1][(j+1)%3],y[1][(j+1)%3])==true){return true;}}}return false; } inline bool check(ll mid) {for(ll i=1;i<=8*n;i++) e[i].clear();memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(ins,0,sizeof(ins));memset(col,0,sizeof(col));tot=scc_cnt=0;while(s.empty()==0) s.pop();for(ll i=1;i<=n;i++){for(ll j=0;j<=3;j++){add(i+j*n,i+(3-j)*n+4*n); add(i+j*n+4*n,i+(3-j)*n);if(out_of_bounds(a[i].first,a[i].second,j,mid)==true) add(i+j*n,i+j*n+4*n);}}for(ll i=1;i<=n;i++){for(ll j=i+1;j<=n;j++){for(ll u=0;u<=3;u++){for(ll v=0;v<=3;v++){if((a[i]==a[j]&&u==v)||triangle_cross(a[i].first,a[i].second,u,a[j].first,a[j].second,v,mid)==true){add(i+u*n,j+v*n+4*n); add(j+v*n,i+u*n+4*n);}}}}}for(ll i=1;i<=8*n;i++) if(dfn[i]==0) tarjan(i);for(ll i=1;i<=4*n;i++) if(col[i]==col[i+4*n]) return false;return true; } int main() { #define Isaac #ifdef Isaacfreopen("city.in","r",stdin);freopen("city.out","w",stdout); #endifll l=0,r,ans=0,mid,i;cin>>w>>h>>n; r=min(w,h);w*=2; h*=2;for(i=1;i<=n;i++) {cin>>a[i].first>>a[i].second;a[i].first*=2; a[i].second*=2;}while(l<=r){mid=(l+r)/2;if(check(mid)==true){ans=mid;l=mid+1;}else{r=mid-1;}}cout<<ans<<".00"<<endl;return 0; }
\(T2_{2}\) HZTG5883. 机关
- 详见 2025省选模拟11 T3 HZTG5883. 机关 。
\(T2_{3}\) HZTG3024. 发烧(fever)
- 详见 2025多校冲刺省选模拟赛12 T1 HZTG3024. 发烧(fever) 。
\(T3\) C. 小 F 的序列
- 原题: UOJ 341. 【清华集训2017】简单数据结构
- 等省选后再来改。
2025省选模拟12
\(T1\) P1019. 国际象棋 \(0pts\)
-
观察到每条对角线上有且仅有一个 \(0\) ,且合法局面下的 \(0\) 一定构成了一段从 \((n,1)\) 到 \((1,m)\) 的路径,途中不经过 \(1\) 。
-
从下往上考虑每条对角线的贡献,如果有 \(0\) ,那么其他位置上一定是 \(1\) ,分段统计不经过 \(1\) 的方案数即可。
点击查看代码
const int p=1000000007; int f[5010][5010],sx[10010],sy[10010],cnt[10010]; char s[5010][5010]; int solve(int x1,int y1,int x2,int y2) {f[x1][y1]=1;for(int i=x1;i<=x2;i++){for(int j=y1;j<=y2;j++) {if(i+1<=x2&&s[i+1][j]!='1') f[i+1][j]=(f[i+1][j]+f[i][j])%p;if(j+1<=y2&&s[i][j+1]!='1') f[i][j+1]=(f[i][j+1]+f[i][j])%p;}}return (x1<=x2&&y1<=y2)*f[x2][y2]; } int main() { #define Isaac #ifdef Isaacfreopen("chess.in","r",stdin);freopen("chess.out","w",stdout); #endifint n,m,ans=1,x=1,y=1,i,j;cin>>n>>m;for(i=1;i<=n;i++){for(j=1;j<=m;j++) cin>>s[n-i+1][j];}if(s[1][1]=='1'||s[n][m]=='1') cout<<0<<endl;else{s[1][1]=s[n][m]='0';for(i=1;i<=n;i++){for(j=1;j<=m;j++) {if(s[i][j]=='0') {cnt[i+j]++;sx[i+j]=i; sy[i+j]=j;}}}for(i=3;i<=n+m&&ans!=0;i++){if(cnt[i]>=2) ans=0;if(cnt[i]==1){ans=1ll*ans*solve(x,y,sx[i],sy[i])%p;x=sx[i]; y=sy[i];}}cout<<ans<<endl;}return 0; }
\(T2_{1}\) P1028. 好段子
-
因为没有 \(std\) 和数据,所以只好口胡。
- 顺延 CF997E Good Subsegments 中扫描线后线段树维护历史版本和的做法,将计算被加了多少次的懒惰标记(时间懒惰标记)从原来的 \(+1\) 改成 \(+r\) 即可。
- 极限数据下跑了 \(0.6s\) ,如果需要进一步卡常的话就把部分
long long
改成int
。答案值域达到了 \(4.17 \times 10^{16}\) ,可能需要unsigned long long
。
点击查看代码
ll a[500010],ans[500010]; vector<pair<ll,ll> >q[500010]; stack<ll>s1,s2; struct SMT {struct SegmentTree{ll minn,num,hsum,tlazy,lazy;}tree[2000010];#define lson(rt) (rt<<1)#define rson(rt) (rt<<1|1)void pushup(ll rt){tree[rt].minn=min(tree[lson(rt)].minn,tree[rson(rt)].minn);tree[rt].num=(tree[lson(rt)].minn==tree[rt].minn)*tree[lson(rt)].num+(tree[rson(rt)].minn==tree[rt].minn)*tree[rson(rt)].num;tree[rt].hsum=tree[lson(rt)].hsum+tree[rson(rt)].hsum;}void build(ll rt,ll l,ll r){if(l==r){tree[rt].minn=0; tree[rt].num=1;return;}ll mid=(l+r)/2;build(lson(rt),l,mid); build(rson(rt),mid+1,r);pushup(rt);}void pushlazy(ll rt,ll lazy,ll tlazy,ll minn){tree[rt].minn+=lazy; tree[rt].lazy+=lazy;if(tree[rt].minn==minn){tree[rt].hsum+=tlazy*tree[rt].num;tree[rt].tlazy+=tlazy;}}void pushdown(ll rt){pushlazy(lson(rt),tree[rt].lazy,tree[rt].tlazy,tree[rt].minn);pushlazy(rson(rt),tree[rt].lazy,tree[rt].tlazy,tree[rt].minn);tree[rt].lazy=tree[rt].tlazy=0;}void update_val(ll rt,ll l,ll r,ll x,ll y,ll val){if(x<=l&&r<=y){tree[rt].minn+=val; tree[rt].lazy+=val;return;}pushdown(rt);ll mid=(l+r)/2; if(x<=mid) update_val(lson(rt),l,mid,x,y,val);if(y>mid) update_val(rson(rt),mid+1,r,x,y,val);pushup(rt);}void update_tim(ll rt,ll l,ll r,ll x,ll y,ll val){if(x<=l&&r<=y){if(tree[rt].minn==0){tree[rt].hsum+=val*tree[rt].num;tree[rt].tlazy+=val;}return;}pushdown(rt);ll mid=(l+r)/2;if(x<=mid) update_tim(lson(rt),l,mid,x,y,val);if(y>mid) update_tim(rson(rt),mid+1,r,x,y,val);pushup(rt);}ll query(ll rt,ll l,ll r,ll x,ll y){if(x<=l&&r<=y) return tree[rt].hsum;pushdown(rt);ll mid=(l+r)/2,ans=0;if(x<=mid) ans+=query(lson(rt),l,mid,x,y);if(y>mid) ans+=query(rson(rt),mid+1,r,x,y);return ans;} }T; int main() { #define Isaac #ifdef Isaacfreopen("seq.in","r",stdin);freopen("seq.out","w",stdout); #endifll n,m,l,r,tmp,i,j;scanf("%lld",&n);for(i=1;i<=n;i++) scanf("%lld",&a[i]);scanf("%lld",&m);for(i=1;i<=m;i++){scanf("%lld%lld",&l,&r);q[r].push_back(make_pair(l,i));}T.build(1,1,n);for(i=1;i<=n;i++){while(s1.empty()==0&&a[s1.top()]>a[i]){tmp=s1.top(); s1.pop();T.update_val(1,1,n,((s1.empty()==0)?s1.top():0)+1,tmp,a[tmp]-a[i]);}while(s2.empty()==0&&a[s2.top()]<a[i]){tmp=s2.top(); s2.pop();T.update_val(1,1,n,((s2.empty()==0)?s2.top():0)+1,tmp,a[i]-a[tmp]);}s1.push(i); s2.push(i);if(i-1>=1) T.update_val(1,1,n,1,i-1,-1);T.update_tim(1,1,n,1,i,i);for(j=0;j<q[i].size();j++) ans[q[i][j].second]=T.query(1,1,n,q[i][j].first,i);}for(i=1;i<=m;i++) printf("%lld\n",ans[i]);return 0; }
\(T2_{2}\) P1020. 樱花树 \(20pts\)
-
原题: luogu P8935 [JRKSJ R7] 茎
-
先不管某个点在操作序列上是否出现及出现在哪个位置,在加入答案时再选择是否要加入操作序列。
-
设 \(f_{x,i}\) 表示以 \(x\) 为根的子树内进行 \(i\) 次操作不必全部删完的方案数,可以先不管 \(x\) 的影响树形背包转移,然后再通过 \(f_{x,i} \gets f_{x,i-1}+f_{x,i}\) 算入 \(x\) 的影响。设 \(g_{x,i}\) 表示以 \(x\) 为根的子树内进行 \(i\) 次操作不必全部删完,其中不操作 \(1 \to x\) 这条根链上的点的方案数,转移同理。
-
对于 \(1 \to x\) 这条根链上的点,如果加入操作序列则往下走的所有点后续不可能再被加入。进行特殊转移,若当前节点不操作则可以直接继承父亲节点的信息,否则一个后缀都可以进行转移,使用后缀和优化优化时间复杂度。接着类似背包将不操作 \(1 \to x\) 这条根链上的点的贡献统计即可。
点击查看代码
const int p=1000000007; struct node {int nxt,to; }e[10010]; int head[5010],siz[5010],f[5010][5010],C[5010][5010],w[5010],g[2][5010],vis[5010],cnt=0; vector<int>s,d; void add(int u,int v) {cnt++; e[cnt]=(node){head[u],v}; head[u]=cnt; } void dfs(int x,int fa,int _x) {s.push_back(x);if(x==_x) d=s;f[x][0]=1;for(int i=head[x];i!=0;i=e[i].nxt){ if(e[i].to!=fa){dfs(e[i].to,x,_x);for(int j=siz[x];j>=0;j--){for(int k=siz[e[i].to];k>=1;k--)f[x][j+k]=(f[x][j+k]+1ll*f[x][j]*f[e[i].to][k]%p*C[j+k][k]%p)%p;}siz[x]+=siz[e[i].to];}}siz[x]++;for(int i=siz[x];i>=1;i--) f[x][i]=(f[x][i-1]+f[x][i])%p;s.pop_back(); } int del(int x) {memset(w,0,sizeof(w));w[0]=1;int siz_x=0;for(int i=head[x];i!=0;i=e[i].nxt){ if(vis[e[i].to]==0){siz_x+=siz[e[i].to];for(int j=siz_x;j>=0;j--){for(int k=siz[e[i].to];k>=1;k--)w[j+k]=(w[j+k]+1ll*w[j]*f[e[i].to][k]%p*C[j+k][k]%p)%p;}}}return siz_x; } int main() { #define Isaac #ifdef Isaacfreopen("tree.in","r",stdin);freopen("tree.out","w",stdout); #endifint n,m,x,u,v,siz_x,sum,i,j,k;cin>>n>>m>>x;C[0][0]=C[1][0]=C[1][1]=1;for(i=2;i<=n;i++){cin>>u>>v;add(u,v); add(v,u);C[i][0]=1;for(j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;} dfs(1,0,x);for(i=0;i<d.size();i++) vis[d[i]]=1;del(1); for(i=0;i<=n-1;i++) g[0][i]=w[i];for(i=1;i<d.size();i++){siz_x=del(d[i]); sum=0;for(j=n-1;j>=0;j--){sum=(sum+g[(i-1)&1][j])%p;if(i==d.size()-1) g[i&1][j]=sum;else g[i&1][j]=(g[(i-1)&1][j]+sum)%p;}for(j=n-1;j>=0;j--){if(g[(i-1)&1][j]!=0){for(k=siz_x;k>=1;k--)if(j+k<=n-1) g[i&1][j+k]=(g[i&1][j+k]+1ll*g[i&1][j]*w[k]%p*C[j+k][k]%p)%p; }}}cout<<g[(d.size()-1)&1][m-1]<<endl;return 0; }
\(T3\) P1021. 长颈鹿会面 \(15pts\)
-
原题: AT_wtf22_day1_d Welcome to Tokyo!
总结
- 参赛体验极差。
- \(Window10\) 下没有虚拟机和双系统,被迫使用 \(Dev-C++\) ,中途想要对拍发现
./可执行文件.exe
用不了,捣鼓了半天 \(cmd\) 和 \(Power Shell\) 无果,无奈使用 \(VsCode\) 终端,但因为 \(VsCode\) 什么插件都没有实际执行的时候出了一堆奇奇怪怪的问题。
- \(Window10\) 下没有虚拟机和双系统,被迫使用 \(Dev-C++\) ,中途想要对拍发现
- \(T1\) 不知道自己 \(n=2\) 的部分分挂在哪里了。
后记
- 因原 \(5\) 道题目都声称之前见过或做过弱化版, \(huge\) 把整套题都换了,原来那套留给我们做练习题用。