2026.10.1 sol
2026.10.1 sol
T1
区间dp,设\(f_{i,j}\)表示考虑区间\(i\)到\(j\)的答案,模板枚举中间\(k\)转移,因为每个人都要握手故状态和转移的长度都为偶数。时间复杂度为\(O(\frac{n^3}{8})\)
code
#include <bits/stdc++.h>
using namespace std;
const int N = 1015;
int m,a[N],n,f[N][N];
int main(){
freopen("toasting.in","r",stdin);
freopen("toasting.out","w",stdout);
scanf("%d",&m);
if(m&1){
puts("0");
return 0;
}
int res = 0;
for(int i = 1 ; i<=m ; i++){
scanf("%d",&a[++n]);
while(n>=2&&a[n]==a[n-1]) n-=2,++res;
}
for(register int l = 2 ; l<=n ; l+=2){
for(register int i = 1 ; i+l-1<=n ; i++){
int j = i+l-1;
for(register int k = i+1 ; k<=j ; k+=2){
int tmp = f[i+1][k-1]+f[k+1][j];
if(a[i]==a[k]) ++tmp;
f[i][j]=max(f[i][j],tmp);
}
}
}
printf("%d",f[1][n]+res);
return 0;
}
T2
没什么好讲的。
code
#include <bits/stdc++.h>
using namespace std;
int rd(){
int w=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while('0'<=ch&&ch<='9'){
w=(w<<3)+(w<<1)+(ch&15);
ch=getchar();
}
return w*f;
}
const int N = 1e5+15;
int n,sum[N],a[N],s;
bool tag;
vector <int> e[N];
void dfs1(int u){
sum[u]=a[u];
for(auto v:e[u]) dfs1(v),sum[u]+=sum[v];
}
bool dfs2(int u,bool tmp){
if(sum[u]==s&&(tmp||tag)) return 1;
for(auto v:e[u]){
if(dfs2(v,tmp||(sum[u]==s*2))) return 1;
}
if(sum[u]==s) tag=1;
return 0;
}
int main(){
freopen("strawberry.in","r",stdin);
freopen("strawberry.out","w",stdout);
int t=rd();
while(t--){
for(int i = 0 ; i<=n ; i++) e[i].clear(),a[i]=sum[i]=0;
n=rd(),tag=0,s=0;int rt=0;
for(int i = 1 ; i<=n ; i++){
int f=rd();a[i]=rd();
e[f].emplace_back(i),s+=a[i];
if(!f) rt=i;
}
if(s%3){puts("NO");continue;}
s/=3,dfs1(rt);
if(dfs2(rt,0)) puts("YES");
else puts("NO");
}
return 0;
}
T3
KMP求出所有匹配的位置然后\(dp\)求解即可
code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+15,p=1000000007;
int add(int a,int b){return a+b>=p?a+b-p:a+b;}
int nxt[N],f[N][2],q[N];
string a,b;
int main(){
freopen("meaning.in","r",stdin);
freopen("meaning.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
memset(nxt,0,sizeof(nxt));
memset(f,0,sizeof(f));
cin>>a>>b;
int n = a.size() , m = b.size();
a=" "+a , b = " "+b;
for(int i = 2 , j = 0; i<=m ; i++){
while(j&&b[i]!=b[j+1]) j = nxt[j];
if(b[i]==b[j+1]) ++j;
nxt[i] = j;
}
int top = 0;
for(int i = 1 , j = 0 ; i<=n ; i++){
while(j&&a[i]!=b[j+1]) j = nxt[j];
if(a[i]==b[j+1]) ++j;
if(j==m) q[++top] = i;
}
f[0][0]=1;
for(int i = 1 , j = 0; i<=top ; i++){
while(q[i]-q[j+1]>=m) ++j;
f[i][0] = add(f[i-1][0],f[i-1][1]);
f[i][1] = add(f[j][0],f[j][1]);
}
cout<<add(f[top][0],f[top][1])<<"\n";
}
return 0;
}
T4
显然可以设\(f_{i,j}\)表示最后一位为第i位,倒数第二位为第j位的最长斐波那契长度。转移有\(f_{i,j}=max(2,f_{j,k}+1)其中a_k=a_i-a_j\),对于\(f_{j,k}\),显然可以记录最大值省去枚举,即记录一个\(mp_{i,j}\)表示结尾为第i位,倒数第二位值为\(j\)的最长长度。时间复杂度为\(O(n^2)\)
code
#include <bits/stdc++.h>
using namespace std;
const int N = 3015;
int n,a[N],f[N][N],ans;
unordered_map <int,int> mp[N];
int main(){
freopen("fibonacci.in","r",stdin);
freopen("fibonacci.out","w",stdout);
scanf("%d",&n);
for(int i = 1 ; i<=n ; i++){
scanf("%d",&a[i]);
for(int j = 1 ; j<i ; j++){
if(mp[j].count(a[i]-a[j])) f[i][j]=mp[j][a[i]-a[j]]+1;
else f[i][j]=2;
mp[i][a[j]]=max(mp[i][a[j]],f[i][j]);
ans=max(ans,f[i][j]);
}
}
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号