2022牛客多校第七场
2022牛客多校第七场
过程
本场首先C题签到,一道小构造,随后F想了想直接暴力删除即可,之后G在理解题意后做出,随后便开始坐牢,队友和我在J上的dp为五次方,没敢下手,,随后在最后时刻想明白了K,但已经没时间下手了,惨淡收场。
题解
C
生成一个排列使得,首先如果全相等则无解,否则我们直接默认,如果只有一个相同的位置,那只要找到一个可交换的交换即可,否则将多个相同的位置依次交换即可。
int n;
int a[maxn],b[maxn];
bool check(){
int now=a[1],flag=1;
rep(i,2,n){
if(a[i]!=now) flag=0;
}
return flag;
}
vector<int>c;
void solve(){
cin>>n;
rep(i,1,n) scanf("%d",&a[i]);
if(check()){puts("NO");return;}
puts("YES");
rep(i,1,n) b[i]=i;
c.clear();
rep(i,1,n){
if(i==a[i]) c.pb(i);
}
if(c.size()==1){
int tmp=c[0];
rep(i,1,n){
if(a[i]!=tmp&&i!=a[tmp]) {
swap(b[i],b[tmp]);break;
}
}
}
else{
int sze=c.size();
rep(i,1,sze-1){
swap(b[c[i]],b[c[i-1]]);
}
}
rep(i,1,n) printf("%d ",b[i]);
pts;
}
F
暴力删除,用双向链表模拟即可,注意判断边界条件和停止条件即可。
int n,x,a[maxn];
int from[maxn],nxt[maxn];
int vis[maxn];
bool check(int now){
bool flag=(a[now]+a[nxt[now]]==x)||(a[now]==a[nxt[now]]);
flag&=(!vis[now] && !vis[nxt[now]]);
flag&=(now!=nxt[now]);
return flag;
}
void solve(){
cin>>n>>x;
rep(i,1,n){
scanf("%d",&a[i]);
from[i]=i-1;
nxt[i]=i+1;
}
from[1]=n;nxt[n]=1;
int now=1,cnt=0;
int ans=0;
while(1){
if(check(now)){
vis[now]=vis[nxt[now]]=1;
from[nxt[nxt[now]]]=from[now];
nxt[from[now]]=nxt[nxt[now]];
now=from[now];ans++;
}
else now=nxt[now];
if(now==nxt[now]) break;
cnt++;
if(cnt>=3*n) break;
}
cout<<ans<<endl;
}
G
题意是表达字符串的最短正则表达式的长度和数量,在理解正则表达式后不难得出结论。
int n;
char s[maxn];
bool check(){
int now=s[1],flag=1;
rep(i,2,n) if(now!=s[i]) flag=0;
return flag;
}
void solve(){
scanf("%s",s+1);
n=strlen(s+1);
bool flag=check();
if(n==1) printf("1 2\n");
else if(n==2) {
if(!flag) printf("2 6\n");
else printf("2 8\n");
}
else{
if(!flag) printf("2 2\n");
else printf("2 4\n");
}
}
J
是一个,但因为跑不满,在判断非法状态后跑的飞快。
首先转换题意,因为是区间和可以被k整除,我们可以等价与前缀和模k后相同的前缀和可以构成一个区间使得区间和被k整除,那么这里将区间和转变为区间的两个端点。令为前缀和模k,为的个数,则,而此时区间和被k整除的个数为,我们要求其等于t时的方案数。
此时设dp状态表示的前缀和的值已被考虑,在个位置中占据了个位置,被k整除的区间个数为,那么最后所求为。考虑如何转移,对于新的,枚举其在n个位置中放多少个,设放个则对于状态,可以有个位置被考虑,因此转移方程。
初始时化,当在前缀和数组上放0时,单独一个位置也算整除k,故初始化时。随后在dp过程中不合法的条件直接跳过,最后dp复杂度看起来是,但实际上远远跑不满,接近.
int n,k,t;
ll dp[70][70][5000];
struct combinatorial{
ll inv[maxn],fac[maxn];
int qpow(ll a,ll b){
ll c=1;
while(b){
if(b&1) c=c*a%mod;
a=1LL*a*a%mod;b>>=1;
}
return c;
}
void build(){
fac[0]=1;
rep(i,1,N) fac[i]=fac[i-1]*i%mod;
inv[N]=qpow(fac[N],mod-2)%mod;
rpe(i,N-1,0) inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(int a,int b){
if(b==0) return 1;
if(a<b) return 0;
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
}com;
void solve(){
com.build();
cin>>n>>k>>t;
rep(j,0,n) dp[0][j][com.C(j+1,2)]=com.C(n,j);
rep(i,0,k-1){
rep(j,0,n){
rep(v,0,t){
if(!dp[i][j][v]) continue;
rep(l,0,n){
if(j+l>n) break;
if(v+com.C(l,2)>n*n) break;
ll &tmp=dp[i+1][j+l][v+com.C(l,2)];
tmp=(tmp+dp[i][j][v]*com.C(n-j,l))%mod;
}
}
}
}
cout<<dp[k-1][n][t]<<"\n";
}
K
博弈+莫队,需要首先分析出博弈的必胜条件。
n堆石子,每堆有个时:
时,先手必胜。
时,若,则后手可以模仿先手操作,后手必胜;若,则选手可以通过取来使得,先手逼胜。
时,对于三个数,不妨令其递增,先手可以从中拿取个,再将合并使得,这样先手必胜。
时,因为先手必胜,所以谁改变堆数谁输,双方均只能拿去,最后终态为全为1,此时先手必输,因此将后,转化为双方取一堆任意石子数量,全取完后无法操作的人输,此时即nim游戏,若的异或和为0,则先手必输,因为后手可以跟着先手做,异或和不为0,则先手可将异或和转为0,后手必输。
时,那么先手可以通过拿取最大的那一堆并将剩下的与其他堆合并使得n变为4且异或和为0,故此时必胜。
时同
因此当n为奇数时必胜,n为偶数且异或和不为0时必胜,为0必输。
那么对于区间询问,因为总的子区间个数为,故求出必输区间减去即可。对于区间内异或和为0的子区间数,可以用莫队来查询,首先处理出的前缀异或和,我们维护两个数组和表示区间内偶数位和奇数位上出现的次数,每次进入当进入莫队当前范围时 ,删除时相反,即可在 内解决问题。
int a[maxn],n,m;
struct Que{int l,r,id,bl;}q[maxn];
ll ans[maxn];
int block;
bool cmp(Que x,Que y){
if(x.bl!=y.bl) return x.l<y.l;
return x.r<y.r;
}
ll now=0;
int s[2][maxm];
void add(int x){
now+=s[x&1][a[x]];s[x&1][a[x]]++;
}
void del(int x){
s[x&1][a[x]]--;now-=s[x&1][a[x]];
}
void Solve(){
cin>>n>>m;;block=n/sqrt(m);
rep(i,1,n) scanf("%d",&a[i]);
rep(i,1,m) {
int x,y;
scanf("%d %d",&x,&y);
q[i]={x-1,y,i,(x-1)/block};
}
rep(i,1,n) a[i]=a[i-1]^(a[i]-1);
sort(q+1,q+1+m,cmp);
int l=0,r=0;s[0][0]=1;
rep(i,1,m){
int L=q[i].l,R=q[i].r;
while(r<R) add(++r);
while(r>R) del(r--);
while(l<L) del(l++);
while(l>L) add(--l);
ll tmp=(r-l+1);
ans[q[i].id]= tmp*(tmp-1)/2 - now;
}
rep(i,1,m) printf("%lld\n",ans[i]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)