2026.10.1 sol

2026.10.1 sol

题面&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;
}
posted @ 2026-10-01 20:59  lrj3247  阅读(8)  评论(0)    收藏  举报