今天莫名其妙就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;
}