CSP2024 前集训:多校A层冲刺NOIP2024模拟赛05

news/2024/10/12 7:12:26

前言

image

一次模拟赛四个计数,后三道一个 trick,yl 他妈都能被气活:

T2、T3、T4 全是正难则反的 trick,T3、T4 都需要回退背包,T1 也可以背包。

T2 没想到正难则反一直死磕心态炸了,其实要试看看 T3 搞不好还想出来了。

以后再想不到正难则反记得抽死我谢谢。

T1 好数

可以直接暴力背包套 bitset 操过去,复杂度 \(O(\dfrac{nv}{w})\)\(v\) 是值域。

也可以移项 \(a+b+c=d\to a+b=d-c\) 开桶 \(O(n^2)\) 维护。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5010,M=6e5+10,V=1e5;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') z=0;for(;isdigit(c);c=getchar()) x=(x<<1)+(x<<3)+(c^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar(' ');write(y...);}
int n,ans,a[N]; bitset<M>f[5];
signed main()
{freopen("number.in","r",stdin),freopen("number.out","w",stdout);read(n); for(int i=1;i<=n;i++) read(a[i]),a[i]+=V;f[0][0]=1; for(int i=1;i<=n;i++){ans+=f[3][a[i]+2*V];for(int j=1;j<=3;j++) f[j]|=(f[j-1]<<a[i]);}write(ans);
}

T2 SOS字符串

正难则反,\(26^n\) 减去 SOS 个数 \(\le 2\) 的,DP 直接转移即可。

赛时一直正着推,没想到就算 SOS 数量固定也会有算重的,遂 \(n\le 12\) 都是错的。

所以以后先把暴力打出来方便拍,还有组合数搞不出来的时候想一想 DP。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1e6+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') z=0;for(;isdigit(c);c=getchar()) x=(x<<1)+(x<<3)+(c^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar(' ');write(y...);}
int n,ans=1,f[2][3][3];
signed main()
{freopen("sos.in","r",stdin),freopen("sos.out","w",stdout);read(n); f[0][0][0]=1;for(int i=1,x=1,y=0;i<=n;i++,x^=1,y^=1,ans=26ll*ans%P) for(int j=0;j<=2;j++){f[x][j][0]=25ll*(f[y][j][0]+f[y][j][2])%P;(f[x][j][0]+=24ll*f[y][j][1]%P)%=P;if(j) (f[x][j][0]+=f[y][j-1][2])%=P;f[x][j][1]=(f[y][j][0]+f[y][j][1])%P;f[x][j][2]=f[y][j][1];}for(int i=0,x=n&1;i<=2;i++) for(int j=0;j<=2;j++) (ans+=P-f[x][i][j])%=P;write(ans);
}

T3 集训营的气球

一样的 trick 正难则反,然后就是回退背包板子。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1e6+10,M=20,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char c=getchar_unlocked();for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,c,m,a[N],b[N]; ll ans=1,f[M];
int inv(ll a,int b=P-2)
{ll res=1; for(;b;(a*=a)%=P,b>>=1) if(b&1) (res*=a)%=P; return res;}
signed main()
{freopen("balloon.in","r",stdin),freopen("balloon.out","w",stdout);read(n,c); f[0]=1;for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<=n;i++) read(b[i]);for(int i=1;i<=n;(f[0]=f[0]*b[i]%P)%=P,(ans*=a[i]+b[i])%=P,i++) for(int j=c-1;j>=1;j--) f[j]=(f[j-1]*a[i]%P+f[j]*b[i]%P)%P;read(m); for(int i=1,o,x,y,sum,va,vb;i<=m;i++) {read(o,x,y); va=inv(a[o]),vb=inv(b[o]),sum=0;(ans*=1ll*inv(a[o]+b[o])*(x+y)%P)%=P,(f[0]*=vb)%=P;for(int j=1;j<c;j++) f[j]=(f[j]-f[j-1]*a[o]%P+P)*vb%P;for(int j=c-1;j>=1;j--) (sum+=(f[j]=(f[j-1]*x%P+f[j]*y%P)%P))%=P;a[o]=x,b[o]=y; write((ans-sum-((f[0]*=y)%=P)+(P<<1))%P),puts("");}
}

T4 连通子树与树的重心

  • 弱化版:P4582 [FJOI2014] 树的重心。

先求出原树的重心,可能有一个或两个,分类讨论。

两个重心

这个比较容易处理,设两个重心分别为 \(u,v\),必定存在边 \((u,v)\),从而分别以两个重心为根跑一遍树形背包。

\(f_{x,i}\) 表示以 \(x\) 为根且块内节点数量为 \(i\) 的连通块的个数,有转移:

\[∀i:[1,sz_x],f_{x,i}=\sum_{y\in son_x}\sum_{j=1}^{\min(i-1,sz[y])}f_{y,j}\times f_{x,i-j} \]

最后答案为 \(\sum\limits_{i=1}^{\max(sz_u,sz_v)}f_{u,i}\times f_{v,i}\)

  • 关于本题树形背包的复杂度:

    转移等价于找出一组 \(x,y\)\(lca(x,y)\) 做出贡献,遂每组 \(x,y\) 只可能被记到一次,遂复杂度为 \(O(n^2)\)

一个重心

先以重心为根跑一遍上面的 DP,然后考虑容斥,依然是正难则反。

求出 \(f_{x,i}\) 中最大子树 \(>\dfrac{i}{2}\) 的即可,回退背包。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
#define pb push_back
using namespace std;
const int N=5010,P=10007;
template<typename Tp> inline void read(Tp&x)
{x=0;register bool z=true;register char c=getchar_unlocked();for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,ans,rt[3],sz[N],mx[N],f[N][N],g[N][N];
vector<int>e[N];
void getrt(int x,int t)
{sz[x]=1; for(int y:e[x]) if(y!=t)getrt(y,x),sz[x]+=sz[y],mx[x]=max(mx[x],sz[y]);mx[x]=max(mx[x],n-sz[x]); if(mx[x]<=(n>>1)) rt[++rt[0]]=x;
}
void dfs(int x,int t)
{sz[x]=1,f[x][0]=f[x][1]=1; for(int y:e[x]) if(y!=t){dfs(y,x),sz[x]+=sz[y];for(int i=sz[x];i;i--) for(int j=1;j<=min(sz[y],i-1);j++)(f[x][i]+=f[x][i-j]*f[y][j]%P)%=P;}
}
signed main()
{freopen("tree.in","r",stdin),freopen("tree.out","w",stdout);read(n); for(int i=1,x,y;i<n;i++) read(x,y),e[x].pb(y),e[y].pb(x);getrt(1,0); if(!(rt[0]&1)){cerr<<1<<endl;dfs(rt[1],rt[2]),dfs(rt[2],rt[1]);for(int i=1;i<=n;i++) (ans+=f[rt[1]][i]*f[rt[2]][i]%P)%=P;return write(ans),puts(""),0;}int x=rt[1]; dfs(x,0); for(int i=1;i<=n;i++) (ans+=f[x][i])%=P;for(int y:e[x]) for(int i=1;i<=n;i++){g[y][i]=f[x][i]; for(int j=1;j<=min(i,sz[y]);j++)(g[y][i]+=P-g[y][i-j]*f[y][j]%P)%=P;}for(int y:e[x]) for(int i=1;i<=n;i++)for(int j=(i+1)/2;j<=min(i,sz[y]);j++)(ans+=P-f[y][j]*g[y][i-j]%P)%=P;write(ans),puts("");
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

【文化课学习笔记】【物理】恒定电流

高中物理学习笔记:恒定电流【物理】恒定电流 电流 基本概念 恒定电流:大小和方向都不变的电流。 直流电:方向不变的电流。 交流电:方向改变的电流。 电流相关 形成:电荷的定向移动。 方向:正电荷移动的方向,即负电荷的反方向,与电子运动方向相反。 定义:单位时间内通过…

数据结构 - 链表

本文介绍了链表的基本概念、节点和头指针的定义,链表的分类及实现方式。通过自申请内存空间和维护,实现了单链表的操作,包括初始化、插入、查找、更新、移除和销毁等操作,并提供了代码示例。今天我们将开始第二个数据类型-链表的学习,同样我们还是用最原始的方式,自己申请…

Design Compiler多时钟约束

这里的资料来源于《Synopsys Timing Constraints and Optimization User Guide, Version P-2019.03-SP4, September 2019》 下面图中这几种情况都是我在实际项目中碰到过的,因此有必要单独做个说明。 第一个是同步派生时钟,即CK2是通过CK1的分频来产生的,我们之前的一个实际…

uniapp创建小程序

uniapp创建小程序https://www.dcloud.io/一、安装Hbuilder和对应基本操作 ​ 安装Hbuilder这里就不在赘述。 (一)、插件安装: ​ 如果考虑到后续需要使用Scss,可以前往插件市场进行搜索安装,浏览器会提示我们是否需要打开对应的HbuilderX,然后进入应用进行安装。(二)…

labelme使用方法

labelme是一款在实例分割、语义分割、目标检测等任务中的一个常用工具,本文将介绍如何使用labelme。 labelme有各种版本,包括ubuntu、windows、macOS等。关于windows版本,也可以下载其相关的exe文件https://github.com/wkentaro/labelme/releases来使用标注 一、安装labelme…

《综合与Design Compiler》笔记

《综合与Design Compiler》笔记 一直没系统的整理过DC这块的东西,这里借助一个挺好的文档《综合与Deisgn Compiler》以及我自己的经验和理解来归总一下。 1. 综合是什么 综合是使用软件的方法来设计硬件,然后将门级电路实现与优化的工作留给综合工具的一种设计方法。它是根据…

C# unsafe 快速复制数组

/// <summary>/// 复制内存/// </summary>/// <param name="dest">目标指针位置</param>/// <param name="src">源指针位置</param>/// <param name="count">字节长度</param>/// <returns&…