其他分享
首页 > 其他分享> > Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)

Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)

作者:互联网

A
容易发现只有进位的时候会出现这种情况。
所以直接输出\(\frac{n+1}{10}\)即可。
code:

int T,n;
int main(){
	freopen("1.in","r",stdin);
	scanf("%d",&T);while(T--){
		scanf("%d",&n);printf("%d\n",(n+1)/10);[]
	}
}

B
暴力枚举两个端点,然后折回去看能不能成立时间复杂度\(O(n^3)\)
但是其实可以hash做到\(O(n^2)\),大概是因为B题没有加强。
code:

using namespace std;
int n,m,k,T;char s1[N+5],s2[N+5];
I int check(int l,int r){
	re int i;if(r*2-l<m||r-l+1>m) return 0;for(i=l;i<=r;i++) if(s1[i]^s2[i-l+1]) return 0;
	for(i=r-1;i>=r-(m-(r-l+1));i--) if(s1[i]^s2[r-i+r-l+1])return 0;return 1; 
}
I void solve(){
	re int i,j,h;scanf("%s",s1+1);scanf("%s",s2+1);n=strlen(s1+1);m=strlen(s2+1);
	for(i=1;i<=n;i++){
		for(j=i;j<=n;j++)if(check(i,j)){printf("YES\n");return;}
	}printf("NO\n");
}
int main(){
	freopen("1.in","r",stdin);
	re int i;scanf("%d",&T);while(T--)solve();
}

C
直接对每个问号爆搜然后取个min即可。
code:

using namespace std;
int T,fl[N+5],now1,now2,ans,n=10;char s[N+5];
I void calc(){
	re int i;now1=now2=0;for(i=1;i<=n;i++){
		if(i&1)now1+=(s[i]=='1');else now2+=(s[i]=='1');
		if((now1>now2&&(n-i+1)/2<now1-now2)||(now1<now2&&(n-i)/2<now2-now1)) {ans=min(ans,i);return;}
	}
}
I void dfs(int x){
	if(x==n+1) return calc();if(fl[x]) s[x]='0',dfs(x+1),s[x]='1',dfs(x+1);else dfs(x+1);
}
I void solve(){
	re int i;scanf("%s",s+1);for(i=1;i<=n;i++) fl[i]=(s[i]=='?');ans=10;dfs(1);printf("%d\n",ans);
}
int main(){
	freopen("1.in","r",stdin);
	scanf("%d",&T);while(T--) solve();
}

D
对起点是奇数起点还是偶数起点两个都算一下即可。
注意要判是否在终点之后也是偶数,我就FST在这里。
code:

int T,n,m,r,las,flag;char s1[N+5],s2[N+5];
I void solve(){
	re int i;scanf("%s%s",s1+1,s2+1);n=strlen(s1+1);m=strlen(s2+1);r=1;las=0;flag=0;
	for(i=1;i<=m;i++){
		while(r<=n&&(s1[r]^s2[i]||((r-las)%2==0))) r++;
		if(r==n+1)break;las=r;r+=(i!=m);
	}flag|=(r!=n+1&&(n-r+1)&1);
	r=las=1;for(i=1;i<=m;i++){
		while(r<=n&&(s1[r]^s2[i]||((r-las)%2==0))) r++;
		if(r==n+1)break;las=r;r+=(i!=m);
	}flag|=(r!=n+1&&(n-r+1)&1);
	puts(flag?"Yes":"No");
}
int main(){
	freopen("1.in","r",stdin);
	scanf("%d",&T);while(T--) solve();
}

E
没看到\(m\leq \frac{n}{3}\)太日了。
可以发现我们最多换\(\frac{2n}{3}\)个位置所以有至少\(\frac{n}{3}\)个位置不动。
然后我们又知道一个点只在一个循环中不动。
所以答案不超过\(3\)
然后暴力数连通块个数即可。
code:

int n,m,T,A[N+5],pl[N+5],F[N+5],cnt,Ans[N+5],fa[N+5],ToT,un,wn;
I int Getfa(int x){return x==fa[x]?x:fa[x]=Getfa(fa[x]);}
I void merge(int x,int y){
	un=Getfa(x);wn=Getfa(y);un^wn&&(fa[un]=wn,ToT--);
}
I void Solve(){
	re int i,j;for(i=0;i<=2*n;i++) F[i]=0;cnt=0;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) scanf("%d",&A[i]),pl[A[i]]=i;
	for(i=1;i<=n;i++) pl[i+n]=pl[i];for(i=1;i<=n*2;i++) i>=pl[i]&&(F[i-pl[i]]++);
	for(i=0;i<n;i++){
		if(F[i]<n-2*m) continue;for(j=1;j<=n;j++) fa[j]=j;ToT=n;for(j=i+1;j<=i+n;j++) merge(j-i,pl[j]);
		n-ToT<=m&&(Ans[++cnt]=(n-i)%n);
	}sort(Ans+1,Ans+cnt+1);printf("%d ",cnt);for(i=1;i<=cnt;i++) printf("%d ",Ans[i]);puts("");
}
int main(){
	freopen("1.in","r",stdin);
	re int i;scanf("%d",&T);while(T--) Solve();
}

F
为什么我的分块和树状数组一样快啊。
首先我们考虑这个式子,其实要求\(G_{i-1}+\sum\limits_{j=1}^{i}{A_i\%A_j}+\sum\limits_{j=1}^{i}{A_j\%A_i}\)后面那个实在平凡暴力跳就好了反正调和级数\(O(nlogn)\),我们看前面那个。
拆成\(\sum\limits_{j=1}^{i}{A_i-A_j\times \lfloor \frac{A_i}{A_j}\rfloor}\)
后面那个直接整除分块+树状数组维护即可,时间复杂度\(O(n\sqrt wlog w)\)
然后观察到我们有\(n\)次修改但是有\(n\sqrt w\)次查询,所以按\(\sqrt w\)分块就可以\(O(n\sqrt w)\)了。
但是他们两个跑得一样快……
code:

int n,k,x,y,z,Maxn;ll G[N+5],ToT,A[N+5],F[N+5];
struct Tree{
	ll F[N+5],Q[N+5];
	I void get(int x,int y){re int i;for(i=x;i<x/k*k+k;i++)F[i]+=y;for(i=x/k+1;i<=Maxn/k;i++)Q[i]+=y;}
	I ll find(int x,int y){return (F[y]+Q[y/k])-(F[x-1]+Q[(x-1)/k]);}
}S1,S2; 
I ll calc1(int m){
	re int i,j;ll Ans=0;for(i=1;i<=m;i=j+1)j=m/(m/i),Ans+=1ll*(m/i)*S1.find(i,j);return Ans;
}
I ll calc2(int m){
	re int i,j;ll Ans=0;for(i=0;i<=Maxn;i+=m){
		Ans+=1ll*(i/m)*m*S2.find(i,min(i+m-1,Maxn)); 
	}return Ans;
}
int main(){
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
	re int i;scanf("%d",&n);k=sqrt(n);for(i=1;i<=n;i++) scanf("%lld",&A[i]),Maxn=max(Maxn,A[i]);
	for(i=1;i<=n;i++){
		G[i]=A[i]*(i-1)+ToT;G[i]-=calc1(A[i])+calc2(A[i]);//printf("%lld %lld\n",calc1(A[i]),calc2(A[i]));
		G[i]+=G[i-1];S1.get(A[i],A[i]);S2.get(A[i],1);ToT+=A[i];printf("%lld ",G[i]);	
	}
}

GHI咕咕咕

标签:everyone,Contest,int,s2,s1,re,code,Div,void
来源: https://www.cnblogs.com/275307894a/p/15057198.html