省选模拟 2
T 营模拟,所以四道题,梦回 NOIP 前模拟赛。
A 石子游戏(stone)
点击查看
天天放博弈论,博弈论是你爹吗?先打表,发现 B 赢麻了,A 赢的时候几乎全是
考虑用 DP 打表,答案与 1,2,和其他数的个数有关
,所以其他数不能变成其他数,只能变成
那如果
考虑现在有
考虑 Bob 的策略,他一定要尽量避免
如果
其他情况 Bob 都可以及时调整。
点击查看代码
#include<bits/stdc++.h> #define fi first #define se second #define pii std::pair<int,int> #define eb emplace_back #define pb push_back typedef long long ll; typedef unsigned long long ull; std::mt19937_64 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count()); inline int R(int n){return myrand()%n+1;} inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;} inline void Min(int &x,int y){if(x>y)x=y;} inline void Max(int &x,int y){if(x<y)x=y;} int n,b[105]; signed main(){ // freopen("in.in","r",stdin);freopen("out.out","w",stdout); std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); int T=read();while(T--){ int a=0; n=read();for(int i=1;i<=n;++i)b[i]=read(),a+=b[i]==1; if(a==n){if(n%3)std::cout<<"Win\n";else std::cout<<"Lose\n";continue;} if(a==n-1){std::cout<<"Win\n";continue;} if(a==n-2){ bool pd=0; for(int i=1;i<=n;++i)if(b[i]==2)pd=1; if(pd&&n%3!=2)std::cout<<"Win\n"; else std::cout<<"Lose\n"; continue; } std::cout<<"Lose\n"; } }
B 树上字符串(treestr)
不难想到预处理
点击查看代码
#include<bits/stdc++.h> #define fi first #define se second #define pii std::pair<int,int> #define eb emplace_back #define pb push_back typedef long long ll; typedef unsigned long long ull; std::mt19937_64 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count()); inline int R(int n){return myrand()%n+1;} inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;} inline void Min(int &x,int y){if(x>y)x=y;} inline void Max(int &x,int y){if(x<y)x=y;} const int N=1e5+10,mod=998244353; inline void W(int &x,int y){x=(x+y)%mod;} int n,q,d[N][32][32],st[20][N],len,fu[N],tmp1[N],tmp2[N],dfn[N],dn; char S[N],T[N]; std::vector<int> e[N],v[N]; inline int get(int x,int y){return dfn[x]<dfn[y]?x:y;} inline void dfs(int x,int fa){ fu[x]=fa; for(int i=1;i<=len;++i)for(int j=1;j<=len;++j)d[x][i][j]=d[fa][i][j]; for(int y:v[x]){ W(d[x][y][y],1); for(int i=y+1;d[fa][i][y+1];++i)W(d[x][i][y],d[fa][i][y+1]); for(int i=y-1;d[fa][i][y-1];--i)W(d[x][i][y],d[fa][i][y-1]); } st[0][dfn[x]=++dn]=fa;for(int v:e[x])if(v^fa)dfs(v,x); if(x==1)for(int i=1;i<=std::__lg(n);++i)for(int j=1;j+(1<<i)-1<=n;++j)st[i][j]=get(st[i-1][j],st[i-1][j+(1<<i-1)]); } inline int LCA(int u,int v){ if(u==v)return u; if((u=dfn[u])>(v=dfn[v]))std::swap(u,v); int d=std::__lg(v-u++);return get(st[d][u],st[d][v-(1<<d)+1]); } inline int query(int u,int v){ int lca=LCA(u,v),f=fu[lca],res=0; for(int i=1;i<=len;++i)tmp1[i]=d[u][i][1],tmp2[i]=d[v][i][len]; tmp1[0]=1;tmp2[len+1]=1; for(int i=1;i<=len;++i)for(int j=i;j;--j)W(tmp1[i],-1ll*tmp1[j-1]*d[f][i][j]%mod); f=lca;for(int i=len;i;--i)for(int j=i;j<=len;++j)W(tmp2[i],-1ll*tmp2[j+1]*d[f][i][j]%mod); for(int i=0;i<=len;++i)W(res,1ll*tmp1[i]*tmp2[i+1]%mod);return (res+mod)%mod; } signed main(){ // freopen("in.in","r",stdin);freopen("out.out","w",stdout); std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); std::cin>>n>>q;for(int i=1;i<n;++i){int u,v;std::cin>>u>>v;e[u].eb(v);e[v].eb(u);} std::cin>>T+1>>S+1;len=strlen(S+1); for(int i=1;i<=n;++i)for(int j=1;j<=len;++j)if(T[i]==S[j])v[i].eb(j); dfs(1,0);for(int i=1;i<=q;++i){int u,v;std::cin>>u>>v;std::cout<<query(u,v)<<"\n";} }
C 区间划分(divid)
注意到这个好区间的数量并不多,最多只有
点击查看代码
#include<bits/stdc++.h> #define fi first #define se second #define pii std::pair<int,int> #define eb emplace_back #define pb push_back typedef long long ll; typedef unsigned long long ull; std::mt19937_64 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count()); inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;} inline void Min(int &x,int y){if(x>y)x=y;} inline void Max(int &x,int y){if(x<y)x=y;} const int N=6e5+10,mod=1e9+7,M=1e6+30; const ll P=100000000000000003; inline void W(int &x,int y){x=(x+y)%mod;} int n,a[N],st[20][N],f[N],lg[N]; ll p[M],s[N]; std::unordered_map<ll,int> mp; inline int get(int x,int y){return a[x]<a[y]?y:x;} inline int Get(int l,int r){int d=lg[r-l+1];return get(st[d][l],st[d][r-(1<<d)+1]);} inline void sol(int l,int r){ if(l>r)return ; if(l==r)return W(f[l],f[l-1]),void(); int mid=Get(l,r);sol(l,mid-1); int L=a[mid],R=L+lg[r-l+1]; if(mid-l+1<=r-mid){ for(int i=l;i<=mid;++i){ for(int ai=L;ai<=R;++ai){ ll ne=(s[i-1]+p[ai])%P; if(mp.find(ne)!=mp.end()){ int wc=mp[ne]; if(wc>=mid&&wc<=r)W(f[wc],f[i-1]); } } } }else{ for(int i=mid;i<=r;++i){ for(int ai=L;ai<=R;++ai){ ll ne=(s[i]-p[ai]+P)%P; if(mp.find(ne)!=mp.end()){ int wc=mp[ne]; if(wc>=l-1&&wc<mid)W(f[i],f[wc]); } } } } sol(mid+1,r); } signed main(){ // freopen("in.in","r",stdin);freopen("out.out","w",stdout); std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); n=read();f[0]=1;lg[0]=-1; for(int i=1;i<=n;++i)lg[i]=lg[i>>1]+1; p[0]=1;for(int i=1;i<=M-10;++i)p[i]=p[i-1]*2%P; mp[0]=0;for(int i=1;i<=n;++i)a[i]=read(),s[i]=(s[i-1]+p[a[i]])%P,st[0][i]=i,mp[s[i]]=i; for(int i=1;i<=std::__lg(n);++i)for(int j=1;j+(1<<i)-1<=n;++j)st[i][j]=get(st[i-1][j],st[i-1][j+(1<<i-1)]); sol(1,n);std::cout<<f[n]<<'\n'; }
D 机器(machine)
经典水龙头接水问题,一个人的贡献是多少个人(包括自己)在等他,那么最小代价的方案就是前
题目没要求在线,可以先把所有人都拿出来,每次操作就相当于停用一个人,启用一个人。把所有人从大到小排序后放到一个
如果
考虑分块,
点击查看代码
#include<bits/stdc++.h> #define fi first #define se second #define pii std::pair<int,int> #define eb emplace_back #define pb push_back typedef long long ll; typedef unsigned long long ull; std::mt19937_64 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count()); inline int R(int n){return myrand()%n+1;} inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;} inline void write(__int128 x){if(x>=10)write(x/10);putchar(x%10+'0');} inline void Min(int &x,int y){if(x>y)x=y;} inline void Max(int &x,int y){if(x<y)x=y;} const int N=6e5+10,LEN=800; int n,K,A[N],Q,tot,num[LEN],match[N],len,ID[N]; ll s[LEN][LEN]; __int128 ans; bool vis[N]; struct NODE{int x,id;}a[N],b[N]; struct QU{int l,r;}q[N]; inline ll c(int rk,int pos){return 1ll*((rk-1)/K+1)*a[pos].x;} inline void pro(int id){ int l=(id-1)*len+1,r=std::min(tot,l+len-1); for(int i=0;i<=len;++i)s[id][i]=0;num[id]=0; for(int i=l,now=0;i<=r;++i)if(vis[i])s[id][now++%K]+=a[i].x,num[id]++; } inline ll get(int id,int x,int pre){int zc=((x-pre)%K+K)%K;if(zc>=len)return 0;return s[id][zc];} inline void work(int l,int r){ int lid=ID[l],rid=ID[r]; if(l<r){ int rk=0;for(int i=1;i<lid;++i)rk+=num[i]; for(int i=l;ID[i]==lid;--i)rk+=vis[i];ans-=c(rk,l); vis[l]=0,vis[r]=1; if(lid==rid){ for(int i=l+1;i<r;++i){rk+=vis[i];if(vis[i])ans-=c(rk,i)-c(rk-1,i);}ans+=c(rk,r); pro(lid); }else{ for(int i=l+1;ID[i]==lid;++i){rk+=vis[i];if(vis[i])ans-=c(rk,i)-c(rk-1,i);} for(int i=lid+1;i<rid;++i)ans-=get(i,0,rk),rk+=num[i]; for(int i=(rid-1)*len+1;i<r;++i){ rk+=vis[i];if(vis[i])ans-=c(rk,i)-c(rk-1,i); }ans+=c(rk,r);pro(lid);pro(rid); } }else{ std::swap(l,r);std::swap(lid,rid); int rk=0;for(int i=1;i<lid;++i)rk+=num[i]; vis[l]=1;vis[r]=0;for(int i=l;ID[i]==lid;--i)rk+=vis[i]; ans+=c(rk,l); if(lid==rid){ for(int i=l+1;i<r;++i){rk+=vis[i];if(vis[i])ans+=c(rk,i)-c(rk-1,i);}ans-=c(rk,r); pro(lid); }else{ for(int i=l+1;ID[i]==lid;++i){rk+=vis[i];if(vis[i])ans+=c(rk,i)-c(rk-1,i);} for(int i=lid+1;i<rid;++i)ans+=get(i,K-1,rk-1),rk+=num[i]; for(int i=(rid-1)*len+1;i<r;++i){ rk+=vis[i];if(vis[i])ans+=c(rk,i)-c(rk-1,i); }ans-=c(rk,r);pro(lid),pro(rid); } } write(ans);putchar('\n'); } signed main(){ // freopen("in.in","r",stdin);freopen("out.out","w",stdout); std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); n=read(),K=read();for(int i=1;i<=n;++i)A[i]=read(),a[++tot]={A[i],i},b[i]={A[i],i}; int Q=read();for(int i=1;i<=Q;++i){ int p=read(),x=read();q[i]={b[p].id,n+i};b[p]={x,n+i};a[++tot]={x,n+i}; }std::sort(a+1,a+tot+1,[](NODE A,NODE B){return A.x>B.x;}); len=std::sqrt(tot); std::sort(A+1,A+n+1,[](int a,int b){return a>b;});for(int i=1;i<=n;++i)ans+=1ll*((i-1)/K+1)*A[i]; for(int i=1;i<=tot;++i)match[a[i].id]=i,ID[i]=(i-1)/len+1; for(int i=1;i<=n;++i)vis[match[i]]=1; for(int i=1;i<=Q;++i)q[i].l=match[q[i].l],q[i].r=match[q[i].r]; for(int i=1;i<=tot;i+=len)pro(ID[i]); for(int i=1;i<=Q;++i)work(q[i].l,q[i].r); }
总结
T2 不会大傻逼,赛时感觉容斥不了就把正解弃了。T1 博弈论不会大傻逼。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】