NOIP2020模拟赛(玖)题解


今天莫名其妙就AK了貌似是水过去的,我还是蒟蒻是最弱的,%%%yzx

A. 「NOIP模拟赛 玖」三个和尚

三个和尚

solve

这道题刚开始没什么头绪,但通过观察发现,\(f(x)\)相同的三个数相加都是3的倍数。我们可以证明

我们发现\(f(x)%3=x%3\),因为x每次减去3的倍数%3都是不会变的

所以\((f(a)+f(b)+f(c))%3=f(a)%3+f(b)%3+f(c)%3=(a+b+c)%3=n%3)\)

又因为\(f(a)=f(b)=f(c)\)

所以\(n%3=0\)

我们就只需要判断\(n%3\)是否等于0

由于这是一道构造题,只要输出答案n/3即可,套一下高精度就好了

code

#include<bits/stdc++.h>
using namespace std;
char s[100005];
int a[100005],b[100005],len_a,len_b,sum,yu;
int main(){
	scanf("%s",s);len_a=strlen(s);
	for(int i=0;i<len_a;i++)a[i]=s[i]-'0',sum+=a[i];
	if(sum%3){printf("-1\n");return 0;}
	if(sum==0){printf("0 0 0\n");return 0;}
	for(int i=0;i<len_a;i++){
		b[len_b++]=(yu+a[i])/3;
		yu=(yu+a[i])%3;
		yu*=10;
	}
	for(int i=1,j;i<=3;i++){
		j=0;
		while(b[j]==0)j++;
		for(;j<len_b;j++)printf("%d",b[j]);
		printf("%c",i<=2?' ':'\n');
	}
	return 0;
}

B. 「NOIP模拟赛 玖」疯狂祖玛

疯狂祖玛

solve

这道题拿到就是一道区间DP关键是怎么定义是问题,我们发现只定义二维\(F[i][j]\)很难去写转移方程,由于n只有100我们可以再定义一维

定义\(F[i][j][k]\)表示i前面有k个和i颜色一样的球是,消除i-j这个区间上所有球需要花费的代价。

想要消除只有两种方式

\((i)\)在左右插球

\((ii)\)从中间分开

在这里要声明一下,在中间插球就是先分开再左右插球,右边插球和左边插球是相对的,所以只要往左边插球就好了。

先考虑初始,因为不算\(a[i]\)那个点,只要再打\(K-k-1\)个球就好了,\(F[i][i][k]=K-k-1\)

求转移方程

\((i)\)

如果前面已经有K-1个球了也就是k=K-1就把a[i]直接消掉,然后把后面消掉\(F[i][j][k]=min(F[i][j][k],f[i+1][j][0])\)

否则的话就塞呗\(F[i][j][k]=min(F[i][j][i],F[i][j][k+1]+1)\)

如果a[i]==a[i+1]的话,那就更新\(F[i][j][k]=min(F[i][j][k],F[i+1][j][min(k+1,K-1)])\)
注意k+1可以超过值域,由于K个以上连续的和K个是等效的,所以要\(min(k+1,min)\)

\((ii)\)

分开来的情况也好处理,我们用一个\(p\)扫过\(i-j\),如果发现\(a[p+1]=a[i]\)那么我们就先把\(i+1\)\(p\)消掉,然后把\(a[p+1]\)\(a[i]\)接到一起消掉。于是转移方程\(F[i][j][k]=min(F[i][j][k],F[i+1][p][0]+F[p+1][j][min(k+1,K-1)])\)

最后思考答案,非常简单\(F[1][N][0]\)不做解释哈哈哈

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int N,K,F[maxn][maxn][maxn],a[maxn];
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
int main(){
	N=read();K=read();
	for(int i=1;i<=N;i++)a[i]=read();
	memset(F,63,sizeof F);
	for(int i=1;i<=N;i++)
	for(int k=0;k<K;k++)F[i][i][k]=K-k-1;
	for(int L=1;L<N;L++)
	for(int i=1;i+L<=N;i++)
	for(int k=K-1,j=i+L;k>=0;k--){
		if(k==K-1)F[i][j][k]=min(F[i][j][k],F[i+1][j][0]);
		else F[i][j][k]=min(F[i][j][k],F[i][j][k+1]+1);
		if(a[i]==a[i+1])F[i][j][k]=min(F[i][j][k],F[i+1][j][min(k+1,K-1)]);
		for(int p=i+1;p<j;p++)if(a[i]==a[p+1])F[i][j][k]=min(F[i][j][k],F[i+1][p][0]+F[p+1][j][min(k+1,K-1)]);
	}
	printf("%d\n",F[1][N][0]);
	return 0;
}

「NOIP模拟赛 玖」回文单词

「NOIP模拟赛 玖」回文单词

solve

我们可以用两个指针向里面推,\(hed\)\(til\),有一个贪心的思想,就是有回文就马上用掉,lst_hed就是上一次的\(hed\),lst_til就是上一次的\(til\),只要发现lst_hedhed和tillst_til相等时,就视为回文串如何快速判断两个串是否相同呢,只要hash就好了,正向hash和反向hash的结果是一样的,原因相见秦九昭定义。

原理上来说,写一个hash就足够了

but!!!我写了4个!!!

还记得ZS说过的哪个创奇,还记得wpy2018的4个hash

在那一刻,我wpy附体!!!

好吧还是一样的,时间还多,慎用啊!!!

code

//我4个哈希,要是挂了那就无语了,哎~ 
#include<bits/stdc++.h>
using namespace std;
const int TT_1=9999991;
const int TT_2=8710747;
const int TT_3=9864191;
const int TT_4=9525721;
int N,len,ans,hed,til,lst_hed,lst_til,hash_h_1,hash_t_1,hash_1=37,F_1[1000005],hash_h_2,hash_t_2,hash_2=31,F_2[1000005],hash_h_3,hash_t_3,hash_3=41,F_3[1000005],hash_h_4,hash_t_4,hash_4=47,F_4[1000005];
char s[1000005];
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
int main(){
	N=read();
	F_1[1]=1;for(int i=2;i<=1000000;i++)F_1[i]=F_1[i-1]*hash_1%TT_1;
	F_2[1]=1;for(int i=2;i<=1000000;i++)F_2[i]=F_2[i-1]*hash_2%TT_2;
	F_3[1]=1;for(int i=2;i<=1000000;i++)F_3[i]=F_3[i-1]*hash_3%TT_3;
	F_4[1]=1;for(int i=2;i<=1000000;i++)F_4[i]=F_4[i-1]*hash_4%TT_4;
	while(N--){
		scanf("%s",s+1);
		len=strlen(s+1);
		hed=1;til=len;ans=0;lst_hed=0,lst_til=til+1;hash_h_1=hash_t_1=0;hash_h_2=hash_t_2=0;hash_h_3=hash_t_3=0;hash_h_4=hash_t_4=0;
		while(hed<til){
			hash_h_1=(hash_h_1*hash_1%TT_1+(s[hed]-'a'+1))%TT_1;
			hash_h_2=(hash_h_2*hash_2%TT_2+(s[hed]-'a'+1))%TT_2;
			hash_h_3=(hash_h_3*hash_3%TT_3+(s[hed]-'a'+1))%TT_3;
			hash_h_4=(hash_h_4*hash_4%TT_4+(s[hed]-'a'+1))%TT_4;
			hash_t_1=(hash_t_1+(s[til]-'a'+1)*F_1[lst_til-til]%TT_1)%TT_1;
			hash_t_2=(hash_t_2+(s[til]-'a'+1)*F_2[lst_til-til]%TT_2)%TT_2;
			hash_t_3=(hash_t_3+(s[til]-'a'+1)*F_3[lst_til-til]%TT_3)%TT_3;
			hash_t_4=(hash_t_4+(s[til]-'a'+1)*F_4[lst_til-til]%TT_4)%TT_4;
			if(hash_h_1==hash_t_1&&hash_h_2==hash_t_2&&hash_h_3==hash_t_3&&hash_h_4==hash_t_4){
				ans+=2;lst_hed=hed;lst_til=til;hash_h_1=hash_t_1=0;hash_h_2=hash_t_2=0;hash_h_3=hash_t_3=0;hash_h_4=hash_t_4=0;
			}
			hed++;til--;
		}
		if(lst_hed!=lst_til-1)ans++;
		printf("%d\n",ans);
	}
	return 0;
}

over


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM