CF Round706简要题解
ABCD
A:贪心 B:讨论 C:贪心 D:讨论
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=1e3+11; int T,N,K; char S[MAXN]; int main(){ T=read(); while(T--){ N=read(),K=read(); scanf("%s",S+1); bool ff=1; for(int i=1;i<=K;i++) if(S[i]!=S[N-i+1]){ff=0;break;} if(!ff){printf("NO\n");continue;} int L=K+1,R=N-K; if(L>R){printf("NO\n");continue;} printf("YES\n"); }return 0; }
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #include<map> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=1e5+11; map<int,int> Ma; int T,N,K,A[MAXN]; int main(){ //freopen("6.in","r",stdin); T=read(); while(T--){ int Maxn=0; N=read(),K=read(); Ma.clear(); for(int i=1;i<=N;i++) A[i]=read(),Maxn=max(Maxn,A[i]),Ma[A[i]]=1; if(!K){printf("%d\n",N);continue;} int mex=0; while(Ma[mex]) ++mex; if(Maxn+1==mex){printf("%d\n",N+K);continue;} int s=(mex+Maxn+1)/2; if(Ma[s]){printf("%d\n",N);continue;} printf("%d\n",N+1); }return 0; }
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second #include<cmath> using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=2e5+11; double XX[MAXN],YY[MAXN];int N,T,tot1,tot2; int main(){ //freopen("1.in","r",stdin); T=read(); while(T--){ tot1=0,tot2=0; N=read(); for(int i=1;i<=N*2;i++){ double x,y; scanf("%lf%lf",&x,&y);x=abs(x),y=abs(y); if(!x) XX[++tot1]=y; if(!y) YY[++tot2]=x; } sort(XX+1,XX+N+1),sort(YY+1,YY+N+1); double res=0; for(int i=1;i<=N;i++) res+=sqrt(XX[i]*XX[i]+YY[i]*YY[i]); printf("%.10lf\n",res); }return 0; }
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=1e5+11; int UL[MAXN],UR[MAXN],DL[MAXN],DR[MAXN],N,U[MAXN],D[MAXN],A[MAXN]; int pre[MAXN],suf[MAXN]; int main(){ //freopen("maker.in","r",stdin); N=read(); for(int i=1;i<=N;i++) A[i]=read(); UL[1]=DL[1]=1; for(int i=2;i<=N;i++){ if(A[i-1]<A[i]) DL[i]=DL[i-1],UL[i]=i; else UL[i]=UL[i-1],DL[i]=i; } UR[N]=DR[N]=N; for(int i=N-1;i>=1;i--){ if(A[i]<A[i+1]) UR[i]=UR[i+1],DR[i]=i; else DR[i]=DR[i+1],UR[i]=i; } for(int i=1;i<=N;i++) U[i]=max(i-UL[i]+1,UR[i]-i+1); for(int i=1;i<=N;i++) D[i]=max(i-DL[i]+1,DR[i]-i+1); for(int i=1;i<=N;i++) pre[i]=max(pre[i-1],U[i]); for(int i=N;i>=1;i--) suf[i]=max(suf[i+1],U[i]); int Ans=0; for(int i=2;i<N;i++){ if(A[i-1]<A[i]&&A[i]>A[i+1]){ if(i-DL[i]+1!=DR[i]-i+1) continue; int LL=DL[i],RR=DR[i]; int res1=max(pre[LL-1],LL-UL[LL]+1),res2=max(suf[RR+1],UR[RR]-RR+1); if(i-LL+1>max(res1,res2)&&((i-LL+1)&1)){ cerr<<i<<endl; Ans++; } } }printf("%d\n",Ans); return 0; }/*s 7 2 5 7 3 1 4 6 */
E
由于题目保证两个 X 之间没有边角连接,那么 X 肯定在 $3\cdot 3$ 正方形的中间,考虑列对 $\bmod 3$ 分类,将 $1,4,7,10,...,3k+1$ 列全变为 X ,在列之间随意打通一个。
注意当 $m\bmod 3$ 时需要特判。
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=511; int T,N,M; char str[MAXN][MAXN]; int main(){ //freopen("3.in","r",stdin); T=read(); while(T--){ N=read(),M=read(); for(int i=1;i<=N;i++) scanf("%s",str[i]+1); for(int i=1+((M%3)==0);i<=M;i+=3){ bool ff=1; for(int j=1;j<=N;j++) str[j][i]='X'; for(int j=1;j<=N;j++) if((str[j][i+1]=='X'||str[j][i+2]=='X')&&ff){str[j][i+1]=str[j][i+2]='X';ff=0;} if(ff){str[1][i+1]=str[1][i+2]='X';} } for(int i=1;i<=N;i++) {for(int j=1;j<=M;j++) printf("%c",str[i][j]);printf("\n");} //printf("============\n"); } }
F
枚举 $S,T$ 。
如果 $S\rightarrow T$ 之间的最短路不止一条那么答案肯定为 $0$ ,证明可以考虑两条路径最后相交的点设为 $x$ ,那么存在两条不交的环,显然从 $T$ 走到第二个路径上最后一个点必定不为最短路。
那么可以将 $S\rightarrow T$ 之间的最短路径摘出来,看成一个大点。定义二元组 $(u,v)$ 表示 $i$ 号点到 $S,T$ 的最短路,那么若两个点在 $dfs$ 树上存在父亲/儿子关系,必然 $u'+1=u,v'+1=v$ 。
可以发现这是一个充要条件。
枚举答案即可。时间复杂度 $O(mn^2)$ 。
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second #define int long long #define mod 998244353 using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=611; int N,M,dis[MAXN][MAXN],d[MAXN],vis[MAXN]; vector<int> vec[MAXN]; queue<int> que; void Get(int u){ dis[u][u]=0; que.push(u); while(!que.empty()){ int xx=que.front(); que.pop(); for(auto v:vec[xx]) if(dis[u][v]>dis[u][xx]+1){dis[u][v]=dis[u][xx]+1;que.push(v);} }return; } int Query(int S,int T){ int res=1,cnt=0; memset(vis,0,sizeof(vis)); for(int u=1;u<=N;u++){ if(dis[S][u]+dis[u][T]==dis[S][T]){ if(vis[dis[S][u]]) return 0; vis[dis[S][u]]=1; d[u]=1;continue; } d[u]=0; for(auto v:vec[u]) if(dis[S][v]+1==dis[S][u]&&dis[T][v]+1==dis[T][u]) ++d[u]; } for(int i=1;i<=N;i++) res*=d[i],res%=mod; return res; } signed main(){ //freopen("4.in","r",stdin); N=read(),M=read(); memset(dis,127/3,sizeof(dis)); for(int i=1;i<=M;i++){int u=read(),v=read();vec[u].pb(v),vec[v].pb(u);} for(int i=1;i<=N;i++) Get(i); for(int i=1;i<=N;i++){ for(int j=1;j<=N;j++) printf("%lld ",Query(i,j));printf("\n"); }return 0; }/* 4 4 1 2 2 3 3 4 1 4 */
G
显然最后被取光的是数量小的,不妨将其颜色设为 $A$ 。
那么取的序列一定是 $ABABAB.../BABABA$ ,对于 $BABABA...$ 的情况我们可以将第一个 $B$ 暴力就能变成第一个情况。
注意到无论如何改变 $A$ 的位置答案均是相同的,因为考虑交换两个相邻的 $A$ ,若他们不在同一个极大 $A$ 联通块中显然交换无影响,若在同一极大联通块依然是对下一个联通块产生贡献,在结果上是相同的。
那么我们将相同的 $A$ 放在一起,维护当前剩余 $A$ 的数量即可。
#include<iostream> #include<cstring> #include<cstdio> #include<climits> #include<algorithm> #include<queue> #include<vector> #define pii pair<int,int> #define mp make_pair #define pb push_back #define fi first #define se second #define int long long #define mod 1000000007 #define LL long long using namespace std; inline int read(){ int f=1,ans=0; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=5e6+11; const int MAXM=2e5+11; int col[MAXN],ret,seed,base,A[MAXN],B[MAXN],N,M,p[MAXM],k[MAXM],b[MAXM],w[MAXM]; int rnd(){ ret=seed,seed=(LL)((LL)seed*base+233)%mod; return ret; } signed main(){ //freopen("A.in","r",stdin); N=read(),M=read(); for(int i=1;i<=M;i++) p[i]=read(),k[i]=read(),b[i]=read(),w[i]=read(); p[0]=0; for(int i=1;i<=M;i++){seed=b[i],base=w[i];for(int j=p[i-1]+1;j<=p[i];j++) col[j]=(rnd()%2)+1,B[j]=A[j]=(rnd()%k[i])+1;} int res1=0,res2=0; for(int i=1;i<=N;i++) if(col[i]==1) res1+=A[i];else res2+=A[i]; int ps=0; if(res1!=res2){ if(res1<res2) ps=1; else ps=2; }else ps=col[1]; int be=0,res=(ps==1)?res1:res2; //for(int i=1;i<=N;i++) cerr<<col[i]<<" ";cerr<<endl; //for(int i=1;i<=N;i++) cerr<<A[i]<<" ";cerr<<endl; int cnt=0; if(col[1]==ps) be=1; else {A[1]--; for(int i=1;i<=N;i++) if(col[i]==ps){be=i;break;}} //for(int i=1;i<=N;i++) cerr<<A[i]<<" ";cerr<<endl; while(res||cnt){ if(A[be]){ if(col[be]==ps){cnt+=A[be];res-=A[be];A[be]=0;} else{ int w=min(A[be],cnt); A[be]-=w; cnt-=w; } } be++; if(be==N+1) be=1; } LL Ans=1; //for(int i=1;i<=N;i++) cerr<<B[i]-A[i]<<" ";cerr<<"\n"; for(int i=1;i<=N;i++) Ans*=(LL)((LL)((B[i]-A[i])^(LL)(i*i))+1)%mod,Ans%=mod; printf("%lld\n",Ans); return 0; }
H
咕咕咕