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