隐藏页面特效

Codeforces Round 869 (Div. 2)

1|0Preface


一把回到紫名还是很舒服的,D题手比较稳猜了点性质水过

主要还是C脑抽了想了挺久才看出来是个丁真题,不然最后过了D之后30min可以看看E的

由于要写学校的图论专题所以接下来一段时间的CF补题计划就要先停一停了


2|0A. Politics


傻逼题,当某个人的串和第一个人有任意一个位置不同时,它就肯定得被请出去

所以看有多少个串和第一个人的串相同即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=105; int t,n,k; char s[N][N]; bool vis[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i,j; for (scanf("%d%d",&n,&k),i=1;i<=n;++i) vis[i]=1,scanf("%s",s[i]+1); for (j=1;j<=k;++j) for (i=1;i<=n;++i) if (s[i][j]!=s[1][j]) vis[i]=0; int ret=0; for (i=1;i<=n;++i) ret+=vis[i]; printf("%d\n",ret); } return 0; }

3|0B. Indivisible


原来还真有这种可以递推的构造题

首先发现n为奇数时除了n=1之外一定无解,因为长度为n的区间必然不满足要求

否则考虑偶数的情况,我们可以从n2的构造情况转移过来

一种合法的方案是类似这样,正确性很容易验证:

2,1,4,3,6,5

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

4|0C. Almost Increasing Subsequence


刚开始各种想复杂结果卡了快40min,不然这场分还能涨

首先容易发现我们可以把一段连续的不升区间放在一起考虑,比如样例就可以划分成:

(1),(2),(4,3,3),(5),(6,2,1)

不难发现每一段长度大于等于2的区间取首尾一定是最优的,因此把长度大于等于2的区间赋权值2,等于1的区间赋权值1

那么询问的时候只要求这段区间的权值和即可,不过要注意两个端点所在的区间的情况要讨论下

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=200005; int n,q,a[N],pos[N],sz[N],cnt,pfx[N],l,r; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); RI i,j; for (scanf("%d%d",&n,&q),i=1;i<=n;++i) scanf("%d",&a[i]); int lst=1; for (i=2;i<=n;++i) if (a[i]>a[i-1]) { for (++cnt,j=lst;j<=i-1;++j) pos[j]=cnt,++sz[cnt]; lst=i; } for (++cnt,j=lst;j<=n;++j) pos[j]=cnt,++sz[cnt]; for (i=1;i<=cnt;++i) pfx[i]=pfx[i-1]+min(sz[i],2); for (i=1;i<=q;++i) { scanf("%d%d",&l,&r); if (pos[l]==pos[r]) printf("%d\n",l==r?1:2); else { int ret=pfx[pos[r]-1]-pfx[pos[l]]; ret+=sz[pos[l]]==1?1:(a[l+1]<=a[l]?2:1); ret+=sz[pos[r]]==1?1:(a[r-1]>=a[r]?2:1); printf("%d\n",ret); } } return 0; }

5|0D. Fish Graph


花式猜结论直接水过可海星,果然图论的本质就是猜结论吗(doge

首先很容易想到BF的做法,对于每个度数大于等于4的点u,枚举两个相邻点当尾巴后在剩下的点里找一个过u的环

但这样的复杂度显然会炸穿,其实我比赛的时候还交了一发喜提TLE

直觉告诉我们应该直接找环然后判断是否存在两个不在环上的点,但如果我们随便找环的话可能会因为DFS的性质把本来可以剩下来的点给占用掉

然后一个很自然的想法就是要找长度最小的环,然后可以证明这样是一定能出解的

因为我们只要找到这个点在环上的两个相邻点,那么最小长度的构造方案一定只占用其中的两个相邻点,否则我们一定可以删去其中的某些点

现在的问题就是怎么找长度最小的环,解决方法大概可以用BFS判环法?

不过由于我前面已经写了DFS判环的代码了,所以加个迭代加深就行

#include<cstdio> #include<iostream> #include<vector> #define RI register int #define CI const int& using namespace std; const int N=2005; int t,n,m,x,y,pre[N],cnt,ansx[N],ansy[N]; bool vis[N]; vector <int> v[N]; inline bool find_cycle(CI now,CI tar,CI len,CI lim,CI lst=0) { if (len>lim) return 0; for (int to:v[now]) if (to!=lst&&to==tar) return pre[to]=now,1; else if (!vis[to]) { vis[to]=1; pre[to]=now; if (find_cycle(to,tar,len+1,lim,now)) return 1; vis[to]=0; } return 0; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i,j,k; for (scanf("%d%d",&n,&m),i=1;i<=m;++i) scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x); bool flag=0; for (i=1;i<=n&&!flag;++i) if (v[i].size()>=4) { for (j=1;j<=n;++j) vis[j]=0; vis[i]=1; if (!find_cycle(i,i,1,n)) continue; for (k=3;k<=n&&!flag;++k) { for (j=1;j<=n;++j) vis[j]=0; vis[i]=1; if (find_cycle(i,i,1,k)) { cnt=0; for (int v:v[i]) if (!vis[v]) { ++cnt; ansx[cnt]=i; ansy[cnt]=v; if (cnt==2) break; } if (cnt<2) break; int now=i; for (;pre[now]!=i;now=pre[now]) ++cnt,ansx[cnt]=now,ansy[cnt]=pre[now]; ++cnt; ansx[cnt]=i; ansy[cnt]=now; for (printf("YES\n%d\n",cnt),i=1;i<=cnt;++i) printf("%d %d\n",ansx[i],ansy[i]); flag=1; } } } if (!flag) puts("NO"); for (i=1;i<=n;++i) v[i].clear(); } return 0; }

6|0E. Similar Polynomials


多项式题,比赛的时候题目没细看就去看学校的图论专题的题了,赛后对着题解补的QWQ(以下所有等式都指模运算下)

首先两个相似多项式的最高次项的系数一定相同,不妨都设为k,然后考虑次高次项,即写出形式:

A(x)=+axd1+kxd,B(x)=+bxd1+kxd

然后由于题目中提到的性质,B(x)=A(x+s),所以有B(xs)=+(bksd)xd1+xd

这里后面的展开就是个二项式定理,就不过多赘述了

因此由比较系数法我们发现令k=[xd]A(x),a=[xd1]A(x),b=[xd1]B(x),则a=bksd,即s=bakd

所以现在的问题就是一个给出多项式的点值求系数的问题了,根据拉格朗日插值的姿势(这篇博客个人觉得还是写的挺好挺详细的),由于这里是连续正数位置的点值,因此:

[xd]f(x)=i=0dyiji1xixj=i=0dyiji1ij=i=0dyi(1)dii!(di)!

直接令ci=(1)dii!(di)!即可计算出k的值了:

[xd]f(x)=i=0dyici

对于d1次项的计算我们可以观察到:

[xd1](xx1)(xxd)=(x1++xd)

所以有:

[xd1]f(x)=i=0dyicijij=i=0dyici(d(d+1)2i)

然后就可以直接算了,总复杂度O(d)

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=2500005,mod=1e9+7; int d,fact[N],ifac[N],A[N],B[N],C[N],k,a,b; inline void inc(int& x,CI y) { if ((x+=y)>=mod) x-=mod; } inline void dec(int& x,CI y) { if ((x-=y)<0) x+=mod; } 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 void init(CI n) { RI i; for (fact[0]=i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod; for (ifac[n]=quick_pow(fact[n]),i=n-1;~i;--i) ifac[i]=1LL*ifac[i+1]*(i+1)%mod; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); RI i; for (scanf("%d",&d),init(d),i=0;i<=d;++i) scanf("%d",&A[i]); for (i=0;i<=d;++i) scanf("%d",&B[i]); for (i=0;i<=d;++i) if (C[i]=1LL*ifac[i]*ifac[d-i]%mod,(d-i)&1) C[i]=mod-C[i]; int tmp=1LL*d*(d+1)/2LL%mod; for (i=0;i<=d;++i) inc(k,1LL*A[i]*C[i]%mod),dec(a,1LL*A[i]*C[i]%mod*(tmp-i+mod)%mod),dec(b,1LL*B[i]*C[i]%mod*(tmp-i+mod)%mod); return printf("%d",1LL*(b-a+mod)*quick_pow(1LL*k*d%mod)%mod),0; }

7|0Postscript


真得珍惜这坎坷的紫名了,希望别下场又滚回去了的说


__EOF__

本文作者hl666
本文链接https://www.cnblogs.com/cjjsb/p/17366594.html
关于博主:复活的ACM新生,目前爱好仅剩Gal/HBR/雀魂/单机/OSU
版权声明:转载请注明出处
声援博主:欢迎加QQ:2649020702来DD我
posted @   空気力学の詩  阅读(167)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示