当前位置: 首页 > news >正文

sm2025 模拟赛11 (2025.10.7)

文章目录

  • T1 木棍
  • T2 巧克力
  • T3 龙脊雪山

T1 木棍

题意
nnn 根木棒,从中选 666 根,将这 666 根拼成一个正方形,任意木棒可以接成一根新的木棒,注意木棒不能弯曲,求总方案数。   1≤n≤5×103,1≤ai≤1071 \le n \le 5 \times 10^3,1 \le a_i \le 10^71n5×103,1ai107

思路
注意到这个正方形的四条边可以形如 {a,a,b+c,d+e}\{a,a,b+c,d+e\}{a,a,b+c,d+e}{a,a,a,b+c+d}\{a,a,a,b+c+d\}{a,a,a,b+c+d} 这两种组合。对两种情况分开讨论。对于第二种可以先对于每个 aaa 预处理出 b+c+d=ab+c+d=ab+c+d=a 的三元组 {b,c,d}\{b,c,d\}{b,c,d} (满足 b≤c≤db\le c \le dbcd);当然也可以枚举 d,ad,ad,ab,cb,cb,c

反思
(n2)×(n−22)≠(n4)\binom{n}{2}\times \binom{n-2}{2} \ne \binom{n}{4}(2n)×(2n2)=(4n)

代码

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5e3+5,maxs=1e7+5;ll C(ll x,ll y){if(x<y) return 0ll;if(y==2) return x*(x-1)/2;if(y==3) return x*(x-1)/2*(x-2)/3;if(y==4) return x*(x-1)/2*(x-2)/3*(x-3)/4;
}ll a[maxn],b[maxn],sum[maxn],f[maxs];
map<int,int>mp;
int main(){freopen("stick.in","r",stdin);freopen("stick.out","w",stdout);int n; cin>>n; int cnt=0;for(int i=1;i<=n;i++){cin>>a[i];if(!mp[a[i]]) mp[a[i]]=++cnt;sum[mp[a[i]]]++;}sort(a+1,a+n+1);for(int i=1;i<=n;i++)b[i]=a[i];int m=unique(b+1,b+n+1)-b-1;ll ans=0;for(int i=1;i<=m;i++)if(sum[mp[b[i]]]>=2){ll fs=0,s=0;for(int j=i-1;j>=1;j--){if(b[i]-b[j]>b[j]) break;int tmp=b[i]-b[j];if(tmp==b[j]){if(sum[mp[tmp]]>=2){fs+=C(sum[mp[tmp]],4);//! C(x,2)*C(x-2,2) ≠C(x,4) fs+=s*C(sum[mp[tmp]],2);s+=C(sum[mp[tmp]],2);}continue;}if(sum[mp[tmp]]){if(sum[mp[b[j]]]>=2&&sum[mp[tmp]]>=2) fs+=C(sum[mp[b[j]]],2)*C(sum[mp[tmp]],2);ll d=sum[mp[tmp]]*sum[mp[b[j]]];fs+=s*d,s+=d;}}ans+=fs*C(sum[mp[b[i]]],2);}for(int i=1;i<=m;i++){for(int j=i+1;j<=m;j++)if(sum[mp[b[j]]]>=3){ans+=sum[mp[b[i]]]*C(sum[mp[b[j]]],3)*f[b[j]-b[i]];if(sum[mp[b[i]]]>=2&&b[j]-2*b[i]>=0&&b[j]-2*b[i]<b[i])ans+=C(sum[mp[b[i]]],2)*C(sum[mp[b[j]]],3)*sum[mp[b[j]-2*b[i]]];if(sum[mp[b[i]]]>=3&&3*b[i]==b[j]) ans+=C(sum[mp[b[i]]],3)*C(sum[mp[b[j]]],3);}for(int j=1;j<i;j++)if(b[i]+b[j]<=b[m]) f[b[i]+b[j]]+=sum[mp[b[i]]]*sum[mp[b[j]]];if(b[i]+b[i]<=b[m]&&sum[mp[b[i]]]>=2) f[b[i]+b[i]]+=C(sum[mp[b[i]]],2);}cout<<ans;return 0;
}

T2 巧克力

link
思路
易知每个连通块的平均数等于全局平均数,考虑先让每个 aia_iai 减去全局平均数(由于平均数会是分数我们将对整体 ×2n\times 2n×2n) ,这样每个连通块的限制化简为 (∑ai)=0(\sum a_i) =0(ai)=0 。记 sumi,jsum_{i,j}sumi,j 表示第 iiiaaa 的前缀和。若连通块在同一行,记 (l,r](l,r](l,r] ,有 sumi,r−sumi,l=0sum_{i,r}-sum_{i,l}=0sumi,rsumi,l=0 ;若连通块跨越两行,记连通块中每一行最右侧的位置为 r0,r1r0,r1r0,r1 ,有 sum0,r0+sum1,r1=0sum_{0,r0}+sum_{1,r1}=0sum0,r0+sum1,r1=0 。这样我们知道如何快速判断一个连通块是否合法。
考虑 DP
有一个想法,设 fi,jf_{i,j}fi,j 表示当前第 000 行考虑到第 iii 位,第 111 行考虑到第 jjj 位且此时已经划分了的块全部合法的块数。发现有如下情况会使这个状态转移不了:
反例
于是再次重新设状态。设 fi,j,kf_{i,j,k}fi,j,k 表示考虑到第 iii 列,(0,i)(0,i)(0,i) 所在块和为 jjj(1,i)(1,i)(1,i) 所在块和为 kkk 此时的块数。复杂度爆炸。考虑优化。发现如果 i,ji,ji,j 在不同的块且两个块的和均不为 000 的话状态没用,因为可以等到块和为 000 的时候再转移。重新记 fi,jf_{i,j}fi,j 表示考虑到第 iii 列,此时第 jjj 行的 (j,i)(j,i)(j,i) 所在块和为 000 ,另一行不确定时分成的最多块数。答案为 max(fn,0,fn,1)max(f_{n,0},f_{n,1})max(fn,0,fn,1)
分讨转移:

  1. 将两行的数并入同一个块中,fi,j←max(fi−1,0,fi−1,1)f_{i,j}← max(f_{i-1,0},f_{i-1,1})fi,jmax(fi1,0,fi1,1)
  2. 只在一行划分一个和为 000 的块,记块为 (k,i](k,i](k,i] ,当 sumj,i−sumj,k=0sum_{j,i}-sum_{j,k}=0sumj,isumj,k=0 ,有 fi,j←fk,j+1f_{i,j}←f_{k,j}+1fi,jfk,j+1
  3. 划分一个横跨两行的块,记另一行在此块中最右侧的位置的左边一位为 kkk (k<ik\lt ik<i),当 sumj,i+sumj⊕1,k=0sum_{j,i}+sum_{j\oplus 1,k}=0sumj,i+sumj1,k=0 时,有 fi,j←fi⊕1,k+1f_{i,j}← f_{i\oplus 1,k}+1fi,jfi1,k+1
  4. 特殊情况:另一行不确定为 000 的部分拼上去上一行和可以为 000 时,即 sum0,i+sum1,i=0sum_{0,i}+sum_{1,i}=0sum0,i+sum1,i=0 时,fi,j←max(fi,0,fi,1)+1f_{i,j}←max(f_{i,0},f_{i,1})+1fi,jmax(fi,0,fi,1)+1

这个 O(n3)O(n^3)O(n3) dp 可以通过 map 优化到 O(n2)O(n^2)O(n2)

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5;
int f[maxn][2];
ll a[2][maxn],sum[2][maxn];
map<ll,int>mp[6];//mp[0(0/1)/1(0/1)][j]
int main(){freopen("sweet.in","r",stdin);freopen("sweet.out","w",stdout);ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int n; cin>>n; ll s=0;for(int i=0;i<=1;i++)for(int j=1;j<=n;j++){cin>>a[i][j];s+=a[i][j];}for(int i=0;i<=1;i++)for(int j=1;j<=n;j++){a[i][j]*=2ll*n,a[i][j]-=s;sum[i][j]=sum[i][j-1]+a[i][j];}mp[0][0]=mp[1][0]=mp[2][0]=mp[3][0]=0;for(int i=1;i<=n;i++){for(int j=0;j<=1;j++){f[i][j]=max(f[i-1][0],f[i-1][1]);int k=(j^1); if(mp[k].count(sum[k][i])) f[i][j]=max(f[i][j],mp[k][sum[k][i]]+1);if(mp[k|2].count(-sum[k][i])) f[i][j]=max(f[i][j],mp[k|2][-sum[k][i]]+1);}if(sum[0][i]+sum[1][i]==0) f[i][0]=f[i][1]=max(f[i][0],f[i][1])+1;for(int j=0;j<=1;j++){mp[j][sum[j][i]]=max(mp[j][sum[j][i]],f[i][j^1]);mp[j|2][sum[j^1][i]]=max(mp[j|2][sum[j^1][i]],f[i][j]);}}cout<<max(f[n][0],f[n][1]);return 0;
}

T3 龙脊雪山

link
由于如果起点确定,能走的山峰是一段区间,可以用的灯笼也是一段区间,于是dp,好像 O(n2)O(n^2)O(n2) dp 挺好想?

http://www.dtcms.com/a/469621.html

相关文章:

  • WebSocket 是什么原理?为什么可以实现持久连接?
  • 【开题答辩全过程】以 宝成花园物业管理系统为例,包含答辩的问题和答案
  • CORS配置实战:SpringBoot与Vite项目的本地联调解决方案
  • 长沙学做网站建设wordpress图片全部压缩
  • [cpprestsdk] 统一资源标识符 | uri_builder
  • 网站开发与运维收费明细报社网站开发做什么
  • 徐州做网站的公司招聘可以做ppt的网站或软件
  • python自带的unittest框架
  • STM32学习记录-0.1 STM32外设
  • 人形机器人:Tesla Optimus的AI集成细节
  • starocks创建表后还需要设置什么
  • 《操作系统真象还原》 第十章 输入输出系统
  • 免费发布信息的网站网站建设规划文档
  • kali安装ARL-docker灯塔
  • Linux的Dynamic debug功能
  • 需要做网站建设的公司做流程图用什么网站
  • 常用的日期时间处理库Day.js和Moment.js
  • Verilog和FPGA的自学笔记5——三八译码器(case语句与锁存器)
  • Mpi多机通信环境搭建(2台机器)
  • 简述网站制作流程图如何免费注册淘宝店铺
  • 人工智能在数学教育中的应用 | 现状、探索与实践
  • VSCode括号高亮插件(vscode插件)bracket pair、活动括号对、括号线(未完全检查)
  • FPGA强化-串口rs232
  • 为何建设银行网站无法登陆公司官网开发
  • 2020年多媒体应用设计师考试上午真题
  • 构建算法远程开发调试环境
  • 南通网站建设系统方案龙岩网站设计 信任推商吧做词
  • Vivado进阶-Fpga中的mem的综合和应用
  • Jmeter设置负载阶梯式压测场景(详解教程)
  • 网站运营专员做六休一wordpress托管网站