今天莫名其妙就AK了貌似是水過去的,我還是蒟蒻是最弱的,%%%yzx
A. 「NOIP模擬賽 玖」三個和尚
link
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模擬賽 玖」瘋狂祖瑪
link
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模擬賽 玖」回文單詞
link
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;
}