CSP模拟58联测20
A.回忆旅途的过往
简单题。最多不超过 10 种数,直接线段树维护 bitset 表示集合种类。修改就是简单的区间覆盖,每一次询问跑一遍完全背包时间开销太大,可以预处理出来,就能做到
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using ll=long long;
int n,m,Q,a[1000005],b[100005],c[15],cnt;
struct offline{int opt,l,r,x;}q[1000005];
struct SegmentTree{
struct node{std::bitset<16> s;int tag;}T[4000005];
inline void pushup(int o){T[o].s=T[o<<1].s|T[o<<1|1].s;}
inline void addtag(int o,int v){T[o].tag=v;T[o].s.reset();T[o].s[b[v]]=true;}
inline void pushdown(int o){
if(~T[o].tag){
addtag(o<<1,T[o].tag);
addtag(o<<1|1,T[o].tag);
T[o].tag=-1;
}
}
void build(int o,int l,int r){
T[o].s.reset();T[o].tag=-1;
if(l==r)return T[o].s[b[a[l]]]=true,void();
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
pushup(o);
}
void modify(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr)return addtag(o,v);
pushdown(o);
int mid=(l+r)>>1;
if(ql<=mid)modify(o<<1,l,mid,ql,qr,v);
if(qr>mid)modify(o<<1|1,mid+1,r,ql,qr,v);
pushup(o);
}
std::bitset<16> query(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return T[o].s;
pushdown(o);
int mid=(l+r)>>1;std::bitset<16> ans;
if(ql<=mid)ans|=query(o<<1,l,mid,ql,qr);
if(qr>mid)ans|=query(o<<1|1,mid+1,r,ql,qr);
return ans;
}
}t;
std::bitset<100005> f[1500];
int h[1500],hash[1500];
int maxV,tot,maxn;
inline int getid(std::bitset<16> x){
int statu=0;
for(int i=10;i;--i)statu=statu*2+x[i];
return hash[statu];
}
int main(){
std::cin.tie(nullptr)->sync_with_stdio(false);
std::cin>>n>>m>>Q;
for(int i=1;i<=n;++i){
std::cin>>a[i];
if(!b[a[i]])b[a[i]]=++cnt,c[cnt]=a[i];
}
for(int i=1;i<=Q;++i){
std::cin>>q[i].opt>>q[i].l>>q[i].r>>q[i].x;
if(q[i].opt==1){if(!b[q[i].x])b[q[i].x]=++cnt,c[cnt]=q[i].x;}
else maxV=std::max(maxV,q[i].x);
}
maxn=1<<cnt;
for(int S=0;S<maxn;++S){
h[++tot]=S;
hash[S]=tot;
}
for(int i=1;i<=tot;++i){
f[i][0]=true;
for(int k=1;k<=10;++k){
if(!(h[i]&(1<<k-1)))continue;
for(int j=c[k];j<=maxV;++j){
f[i][j]=f[i][j]|f[i][j-c[k]];
}
}
}
t.build(1,1,n);
for(int i=1;i<=Q;++i){
if(q[i].opt==1)t.modify(1,1,n,q[i].l,q[i].r,q[i].x);
else{
f[getid(t.query(1,1,n,q[i].l,q[i].r))][q[i].x]?
std::cout<<"Yes\n":std::cout<<"No\n";
}
}
return 0;
}
B.牵着她的手
可以观察到序列合法的充要条件是
必要性显然,充分性可以构造一个矩阵,让那一行与列的交点填最大值,那一行与列的其他位置填任意数,其余位置看作等价的,都填
然后就可以枚举最大值,不难推出答案
点击查看代码
#include<bits/stdc++.h>
using ll=long long;
constexpr int P=1e9+7;
inline ll qpow(ll a,ll b){ll ans(1);for(;b;b>>=1,a=a*a%P)if(b&1)ans=ans*a%P;return ans;}
int n,m,k,fn[200005],fm[200005],isp[200005],tot;
int g[200005],pre[200005],suf[200005],fac[200005],inv[200005];
inline void linear_sieve(int x){
tot=0;for(int i=2;i<=x;++i)fn[i]=fm[i]=0;
fn[0]=fm[0]=0;fn[1]=fm[1]=1;
for(int i=2;i<=x;++i){
if(!fn[i])fn[i]=qpow(i,n),fm[i]=qpow(i,m),isp[++tot]=i;
for(int j=1;j<=tot&&1ll*isp[j]*i<=x;++j){
fn[isp[j]*i]=1ll*fn[isp[j]]*fn[i]%P;
fm[isp[j]*i]=1ll*fm[isp[j]]*fm[i]%P;
if(i%isp[j]==0)break;
}
}
}
inline void prework(int x,int lim){
linear_sieve(lim);
for(int i=1;i<=lim;++i)g[i]=(g[i-1]+1ll*(fn[i]-fn[i-1])*(fm[i]-fm[i-1])%P)%P;
pre[0]=suf[lim+1]=1;
for(int i=1;i<=lim;++i)pre[i]=1ll*pre[i-1]*(x-i)%P;
for(int i=lim;i;--i)suf[i]=1ll*suf[i+1]*(x-i)%P;
}
inline int lagrange(int x,int y){
int ans(0);
for(int i=1;i<=y;++i)
ans=(ans+((y-i)&1?-1ll:1ll)*g[i]*pre[i-1]%P*suf[i+1]%P*inv[i-1]%P*inv[y-i]%P)%P;
return (ans+P)%P;
}
inline void solve(){
std::cin>>n>>m>>k;
prework(k,n+m+2);
std::cout<<lagrange(k,n+m+2)<<'\n';
}
int main(){
std::cin.tie(nullptr)->sync_with_stdio(false);
fac[0]=inv[0]=1;
for(int i=1;i<=200002;++i)fac[i]=1ll*fac[i-1]*i%P;
inv[200002]=qpow(fac[200002],P-2);
for(int i=200001;i;--i)inv[i]=1ll*inv[i+1]*(i+1)%P;
int T;std::cin>>T;while(T--)solve();
return 0;
}
C.注视一切的终结
不会。
D.超越你的极限
不会。树形 dp 30pts。取前缀
点击查看代码
#include<bits/stdc++.h>
using ll=long long;
std::vector<std::pair<int,int>> g[1005];
int n,w[1005];
ll dp[1005][1005];
void dfs(int x,int f){
int mn=1000;
for(auto &y:g[x]){
if(y.second==f)continue;
mn=std::min(mn,y.first);
dfs(y.second,x);
}
for(int i=0;i<=mn;++i){
ll tot=0;
for(auto &y:g[x]){
if(y.second==f)continue;
tot+=dp[y.second][y.first-i];
}
dp[x][i]=(ll)i*w[x]+tot;
}
for(int i=1;i<=1000;++i)dp[x][i]=std::max(dp[x][i],dp[x][i-1]);
}
int main(){
std::cin.tie(nullptr)->sync_with_stdio(false);
std::cin>>n;for(int i=1;i<=n;++i)std::cin>>w[i];
for(int i=1,x,y,z;i<n;++i)std::cin>>x>>y>>z,g[x].push_back({z,y}),g[y].push_back({z,x});
dfs(1,0);
std::cout<<dp[1][1000]<<std::endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现