隐藏页面特效

Codeforces Round #832 (Div. 2)

1|0Preface


感觉现在水平有点迷了,D秒出的正解然后被一个细节搞了一直过不去,打完对着代码看一眼就发现了

场场掉分这谁顶得住啊


2|0A. Two Groups


SB题,把所有正数和负数分开放即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; int t,n,x; long long t1,t2; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d",&n),t1=t2=0,i=1;i<=n;++i) if (scanf("%d",&x),x>0) t1+=x; else t2+=x; printf("%lld\n",max(t1,-t2)-min(t1,-t2)); } return 0; }

3|0B. BAN BAN


就这SB题我还WA了一发

考虑对于每个长度为3的块,我们把它和关于中心对称位置上的数交换就可以做到n2的复杂度了

举个例子,对于n=5的情形,有

BAN BAN BAN BAN BANNAN BAN BAN BAN BABNAN NAN BAN BAB BABNAN NAN NAB BAB BAB

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=305; int t,n,a[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d",&n),printf("%d\n",n+1>>1),i=1;i<=n+1>>1;++i) printf("%d %d\n",3*(i-1)+1,3*n-(3*(i-1)+1)+1); } return 0; }

4|0C. Swap Game


现在拿到这种博弈我都是先码个暴力然后开始找性质,然后猜个结论直接过

先给出结论:若a1是整个序列中的最小值,那么先手必败,否则先手必胜

证明的话考虑用归纳法,设m=mini=1nai,当m=1时:

  • a1=1,显然此时先手必败
  • a11,此时先手可以把后面的1换到前面来,就转化成了必败态,因此此时先手必胜

设当m=t时结论成立,当m=t+1时:

  • a1=t+1,无论先手把这个数换到哪里,后手只要把它换回来就转化成了a1=t的先手必败态,因此此时先手必败
  • a1t+1,先手只要把后面的t+1换到前面来即可,此时先手必胜

因此结论成立,直接做即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=100005; int t,n,a[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]); bool flag=0; for (i=2;i<=n&&!flag;++i) if (a[1]>a[i]) flag=1; puts(flag?"Alice":"Bob"); } return 0; }

5|0D. Yet Another Problem


妈的写错一个巨ZZ的地方害得我一直以为思路有问题,最后心态爆炸

大致问题就是我开了一个map <int,vector <int>> s[2];然后想在每一个存在的元素后面加一个n+1,结果这样写

for (auto v:s[0]) v.second.push_back(n+1); for (auto v:s[1]) v.second.push_back(n+1);

直接寄了,因为这只是修改迭代器对应的值,并没有真正修改要改的地方,后面写成这样就可以了

for (auto v:s[0]) s[0][v.first].push_back(n+1); for (auto v:s[1]) s[1][v.first].push_back(n+1);

好了下面开始讲正题

首先我们分别考虑二进制下每一位,不难发现我们的操作不会改变这一位上1的数目的奇偶性

因此每一位上1的个数必须是偶数,因此一个有解的充要条件是区间的异或和为0

接下来考虑算答案,首先先特判掉区间内全为0的情况,然后如果区间长度是奇数答案也显然是1

考虑区间长度为偶数的情况,先排除掉两个端点存在0的情形,此时答案仍然为1

否则我们可以把一个长度为偶数的区间划分成两个长度为奇数的区间,只要保证两个子区间的异或和都为0即可

由异或的性质知找到一个子区间[l,k],k<r]2kl+1即可,即找到pfxk=pfxl1,其中pfx为异或前缀和

我们可以把下标奇偶分开讨论,考虑用map记录下满足pfxi=x对应的i下标集合

然后询问的时候在上面二分找到第一个出现在l后面的下标,判断是不是在r之前即可

(其实只要从前往后扫一遍记录下每个数能和它凑出的长度最短的异或和为0的奇数区间的下标即可,但是比赛的时候太执着于算法本身的正确性而没去想实现的细节错误)

#include<cstdio> #include<iostream> #include<map> #include<vector> #define RI register int #define CI const int& using namespace std; const int N=200005; int n,q,a[N],pfx[N],l,r; map <int,vector <int>> s[2]; long long sum[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); RI i; for (scanf("%d%d",&n,&q),s[0][0].push_back(0),i=1;i<=n;++i) scanf("%d",&a[i]),pfx[i]=pfx[i-1]^a[i],sum[i]=sum[i-1]+a[i],s[i&1][pfx[i]].push_back(i); for (auto v:s[0]) s[0][v.first].push_back(n+1); for (auto v:s[1]) s[1][v.first].push_back(n+1); for (i=1;i<=q;++i) { scanf("%d%d",&l,&r); int cur=pfx[r]^pfx[l-1]; if (sum[r]-sum[l-1]==0) { puts("0"); continue; } if (cur) { puts("-1"); continue; } if ((r-l+1)&1) { puts("1"); continue; } if (a[l]==0||a[r]==0) { puts("1"); continue; } if (!s[l&1].count(pfx[l-1])) { puts("-1"); continue; } int pos=*lower_bound(s[l&1][pfx[l-1]].begin(),s[l&1][pfx[l-1]].end(),l); puts(pos<=r?"2":"-1"); } return 0; }

6|0E. List Generation


思维妙题,很有AGC风格的一道题

首先问题可以被转化为坐标系走路,从(0,0)(n,m)的路径上选出一个点集,求所有本质不同的点集的大小之和

由于一个点集可能会有多条包含它的路径,我们为了不计重,考虑强制从一个点到另一个点的路径是先上再右,不难发现此时点集和路径唯一对应

因此现在先考虑路径的方案数,对于这种坐标系上走路的问题一个常用的trick就是统计拐点

我们枚举拐点数目i,不难发现此时方案数为Cni×Cmi,此时路径已经被唯一确定

考虑剩下的s=n+mi1个点(除去拐点和起点终点),接下来考虑这些点的贡献

枚举在这s个点中选择的点数j,则总贡献为j=0sCsj×j=s×2s1

注意还要算上起点终点和拐点的贡献,这部分是(i+2)×2s

总复杂度O(n+m),代码的话非常简单了

#include<cstdio> #define RI register int #define CI const int& using namespace std; const int N=10000005,mod=1e9+7; int t,n,m,fac[N],ifac[N],pw[N]; inline int sum(CI x,CI y) { return x+y>=mod?x+y-mod:x+y; } inline int quick_pow(int x,int p=mod-2,int mul=1) { for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul; } inline int C(CI n,CI m) { if (n<0||m<0||m>n) return 0; return 1LL*fac[n]*ifac[m]%mod*ifac[n-m]%mod; } inline void init(CI n) { RI i; for (fac[0]=i=1;i<=n;++i) fac[i]=1LL*fac[i-1]*i%mod; for (ifac[n]=quick_pow(fac[n]),i=n-1;~i;--i) ifac[i]=1LL*ifac[i+1]*(i+1)%mod; for (pw[0]=i=1;i<=n;++i) pw[i]=sum(pw[i-1],pw[i-1]); } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (init(10000000),scanf("%d",&t);t;--t) { scanf("%d%d",&n,&m); int ans=0,s; for (RI i=0;i<n+m;++i) s=n+m-i-1, ans=sum(ans,1LL*sum(1LL*pw[s]*(i+2)%mod,1LL*(s?pw[s-1]:0)*s%mod)*C(n,i)%mod*C(m,i)%mod); printf("%d\n",ans); } return 0; }

7|0Postscript


这场巨可惜,本来四题保底的,结果变成了这样

感觉比赛的时候思路没有平时清晰啊,看来得多多实战找感觉


__EOF__

本文作者hl666
本文链接https://www.cnblogs.com/cjjsb/p/16864918.html
关于博主:复活的ACM新生,目前爱好仅剩Gal/HBR/雀魂/单机/OSU
版权声明:转载请注明出处
声援博主:欢迎加QQ:2649020702来DD我
posted @   空気力学の詩  阅读(67)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示