浙江农林大学第二十一届程序设计竞赛校选拔赛A E G H

这篇博客探讨了两个编程题目,一个是关于电梯乘坐概率的动态规划问题,另一个涉及字符串中特定子串出现的区间查询。文章通过分析题目,给出了相应的解决方案,包括动态规划状态转移方程和利用后缀数组进行区间查询的方法,并提供了C++代码实现。
摘要由CSDN通过智能技术生成

A 瓜瓜的春天 传送门

题意:电梯前有两列队伍,电梯一次可以坐两人,其中

  • 有 25% 的可能,电梯是满的,没有办法乘坐电梯;
  • 有 25% 的可能,电梯是空的,则两队队首都可以乘坐电梯;
  • 有 50% 的可能,电梯里已经有一个人,则两队队首乘坐的概率均等。

求第一列第 i 个人与第二列第 j 个人同时坐上电梯的概率。

分析:概率dp。电梯满的情况相当于没来,这种可能划去。即

  • 有 1/3 的可能,两人同时上
  • 有 1/3 的可能,左边队伍上一人
  • 有 1/3 的可能,右边队伍上一人

因此定义dp[i][j]为左边队伍第i个人与右边队伍第j个人同时在队首的概率。

转移方程为dp[i][j]=1/3*(dp[i-1][j]+dp[i][j-1]+dp[i-1][j-1])

两人同时上的概率为1/3*dp[i][j] 。

另外卡了内存,需要开一个滚动数组。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int dp[2][10005];

signed main()
{
	int x,y;
	cin>>x>>y;
	dp[1][1]=1;
    int inv3=332748118;
	for(int i=1;i<=x;i++)
	{
		for(int j=1;j<=y;j++)
		{
			if(i==1&&j==1) continue;
			dp[i&1][j]=(dp[(i-1)&1][j]+dp[i&1][j-1]+dp[(i-1)&1][j-1])*inv3%mod;
		}
	}
	cout<<dp[x&1][y]*inv3%mod<<endl;
}

E 俺拜俺拜 传送门

题意:给定一个由ab组成的字符串,求区间长度大于等于x且ab个数相同的区间是否存在。

分析:时间复杂度上显然只能O(n)扫一遍,令a=1,b=-1,考虑计算序列前缀和{Si},若Si=Sj,说明i到j之间a和b的数量相等。

代码

#include<bits/stdc++.h>
using namespace std;
char c[10005];

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		map<int,int>mp;
		mp[0]=0;//
		int n,x;
		cin>>n>>x;
		scanf("%s",c+1);
		int cnt=0;
		int f=0;
		for(int i=1;i<=n;i++)
		{
			if(c[i]=='a') cnt++;
			else cnt--;
			if(mp.count(cnt))//又回到了曾经的数目 说明中间这段ab相等
			{
				if(i-mp[cnt]>=x)
				{
					f=1;
					cout<<mp[cnt]+1<<" "<<i<<endl;
					break;
				}
			}
			else mp[cnt]=i;
		}
		if(f==0) cout<<"impossible"<<endl;
	}
}

G 瓜瓜的特别任务

题意:求字符串中子串的最大循环次数。

分析:O(n^2logn)+break。利用后缀数组可以做到O(nlogn)。

代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t;
	cin>>t;
	while(t--)
    {
		string a;
		cin>>a;
		int s=a.length();
		int ans=1;
		for(int l=1;l<=s;l++)//长度 
        {
			if(s/l<=ans) break;
			for(int i=0;i<s;i++)//起点 
            {
            	int j=i+l;//终点 
				if(j>s) break;
				string tmp=a.substr(i,l);
				int cnt=1,pos=i;
				while(pos+l-1<s&&tmp==a.substr(pos+l,l))
                {
					pos+=l;
					cnt++;
				}
				ans=max(ans,cnt);
			}
		}
		printf("%d\n",ans);
	}
}

后缀数组代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
int xx[N],yy[N],cnt[N];
int sa[N],rk[N],ht[N];//sa[i]:排名为i的后缀的起始位置;rk[i]:起始位置为i的后缀的排名
char s[N];
int n;

void getsa(int n,int M)
{
    int i,j,p,*x=xx,*y=yy;
    for(i=0;i<M;i++)cnt[i]=0;
    for(i=0;i<n;i++)cnt[x[i]=s[i]]++;
    for(i=1;i<M;i++)cnt[i]+=cnt[i-1];
    for(i=n-1;i>=0;i--)sa[--cnt[x[i]]]=i;
    for(j=1,p=1;p<n;j<<=1,M=p)
	{
        for(p=0,i=n-j;i<n;i++)y[p++]=i;
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        for(i=0;i<M;i++)cnt[i]=0;
        for(i=0;i<n;i++)cnt[x[y[i]]]++;
        for(i=1;i<M;i++)cnt[i]+=cnt[i-1];
        for(i=n-1;i>=0;i--)sa[--cnt[x[y[i]]]]=y[i];
        for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
    }
}

void getht(int n)//求完这个才最终求出sa 并求出rk ht  
{
    int i,j,k=0;
    for(i=1;i<=n;i++)rk[sa[i]]=i;
    for(i=0;i<n;ht[rk[i++]]=k)
        for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
    for(i=n;i;i--)rk[i]=rk[i-1],sa[i]++;
}

int dp[N][20];
void RMQ()
{
    for(int i=1;i<=n;i++) dp[i][0]=ht[i];
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)
            dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
}

int query(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=(r-l+1)) ++k;
    return min(dp[l][k],dp[r-(1<<k)+1][k]);
}

int lcp(int i,int j)
{
    i=rk[i],j=rk[j];
    if(i>j) swap(i,j);
    return query(i+1,j);
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
    	scanf("%s",s);
    	n=strlen(s);
        getsa(n+1,300);//字符串:n+1,300;数字:n+1,离散化后N 
		getht(n);
        RMQ();
        int ans=1;//最少是1 
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j+i<=n;j+=i)
            {
                int now=lcp(j,j+i);
                int num=now/i+1;
                int k=j-(i-now%i);
                if(k>0&&lcp(k,k+i)>=i) num++;
                ans=max(ans,num);
            }
        }
        printf("%d\n",ans);
    }
}

H 磊爷与佣兵战记

题意:n个好友,m对关系,初始战斗力全为0。当一个好友战斗力提升x时会带动他的好友战斗力提升x(但是不会带动好友的好友再次提升)。
给定 q个操作:

  •   1 p x,代表某人战斗力提升 x;
  •   2 p,代表查询某人的战斗力。

分析:根号分治,将度数小于等于根号m的点作为小点,对于度数大于根号m的点作为大点。更新小点时,对周围的点暴力更新;更新大点时,另开一个lazy数组,更新在lazy数组上。查询某个点时我们先预处理把大点周围的点对大点连边,之后只需要遍历该点连向的大点就可以了。这样的话新图大概有sqrt(m)条单向边,复杂度O(q*sqrt(m))。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+5;
vector<int>e[maxn],e2[maxn];
int f[maxn];
int lazy[maxn];
 
signed main()
{   
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int u,v;
        cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    int sz=sqrt(m);
    for(int i=1;i<=n;i++)
    {
        if(e[i].size()>sz)
        {
            for(int j:e[i])
            {
                e2[j].push_back(i);
            }
        }
    }
    int q;
    cin>>q;
    while(q--)
    {
        int op;
        cin>>op;
        int p,x;
        cin>>p;
        if(op==1)
        {
            cin>>x;
            f[p]+=x;
            if(e[p].size()<=sz) for(int j:e[p]) f[j]+=x;
            else lazy[p]+=x;
        }
        else
        {
            int now=f[p];
            for(int i:e2[p]) now+=lazy[i];
            cout<<now<<endl;
        }
    }
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chmpy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值