week8——csp模拟题t1,t2,t4

Problem1——HRZ的序列

问题描述
问题分析

如果这个数列是在这里插入图片描述满足情况的,只会有三种情况,1全是一样的数字,每个数字不变即可达到目标。2总共有两个数字,其中一种数字加上k可以变成另一种数字。3有三种数字,分别对应的操作是,加k,不变,减k。
于是我先是对每一个输入进来的数据先进行去重,是一样的数字,或者不一样但是不一样数字的个数小于等于三。一旦超过三,就判断为NO。然后对于判重后的数字进行一下排序。如果是三个数字,那么最小的数字加上最大的数字一定等于中间那个数字的两倍。如果是一个或者两个数字,则不需要判断,直接是对的。
这个的算法比较简单,复杂度只有n。

代码
#include<iostream>
using namespace std;
#include<algorithm>
long long a;//[10001];
int t,n;
long long ans[3];
bool pan=true;
bool cmp(long long a,long long b)
{
	return a<b;
 } 
int main()
{
	scanf("%d",&t);
	for(int k=0;k<t;k++)
	{
		scanf("%d",&n);
		ans[0]=0;//初始化 
		ans[1]=0;
		ans[2]=0;
		pan=true;
		for(int i=0;i<n;i++)
		{
			scanf("%lld",&a);
			//cout<<a<<endl;
			for(int j=0;j<3;j++)
			{
				if(ans[j]==0)
				{
					ans[j]=a;
					//cout<<"   kong="<<a<<endl;
					break;
				}
				else if(ans[j]==a)
				{
					//cout<<"   youle"<<a<<endl;
					break;
				}
				else if(j==2&&ans[j]!=a)
				{
					//cout<<"   duole"<<a<<endl;
					pan=false;
					break;
				}
			}
		}
		sort(ans,ans+3,cmp);
		//for(int i=0;i<3;i++)
		//cout<<ans[i]<<endl;
		//cout<<"    yayaya"<<ans[0]+ans[2]<<"     wwww"<<ans[1]*2<<endl;
		if(pan&&ans[0]+ans[2]==ans[1]*2)
		{
			printf("YES");
		}
		else if(ans[0]==0||ans[1]==0||ans[2]==0)
		{
			printf("YES");
		}
		else
		{
			printf("NO");
		}
		if(k!=t-1)
		printf("\n");
	}
	
	return 0;
}
遇到的问题

情况没考虑全面,想到什么写什么,导致只有一种大小数字的情况没有想到,以后一定先分析一下情况再开始描写。

Problem2——HRZ 学英语

问题描述

在这里插入图片描述
在这里插入图片描述

问题分析

采用了尺取法,选取区间,判断该区间是否符合要求,不符合要求左区间往右移,直到满足条件(不是得到答案的那种满足条件,只是每个字母出现的个数和总共区间的长度),因为描述了里面只有26个大写字母和?,所以就用了数组vis[]确定每个大写字母在我所选择的区间的个数,一旦超过1,则这个选择的区间就是不合格的。不合格就让左端点往右移动,并对应出区间的字符做出相应的改变操作。

代码
#include<iostream>
using namespace std;
char zi[1000001];
int vis[27];
char English[26]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int num=0;
int main()
{
	cin>>zi;
	int left=0,right=0;
	int shu;
	for(int i=0;i<27;i++)
	vis[i]=0;
	while(zi[right]!='\0'&&left<=right)
	{
		//cout<<"left="<<left<<"    right="<<right<<endl;
		if(zi[right]=='?')
		{
			num++;
			right++;
		}
		else 
		{
			shu=zi[right]-'A';
			//cout<<"   shu="<<shu<<"  zi="<<zi[right]<<endl;
			if(vis[shu]==0)//满足条件
			{
				vis[shu]=1;
				num++;
				right++;
			} 
			else if(vis[shu]==1)//不满足条件
			{
				if(zi[left]=='?')
				num--;
				else
				{
					vis[zi[left]-'A']=0;
					num--;
				}
				
				
				left++;
				
		 	} 
		}
		//cout<<num<<endl;
		if(num==26)
		{
			break;
		}	
	}
	/*for(int i=left;i<left+26;i++)
		{
			cout<<zi[i]<<" ";
			
		}
		cout<<endl;
			for(int i=0;i<26;i++)
		{
			cout<<vis[i]<<" ";
			
		}*/
	if(num==26)
	{
		for(int i=left;i<left+26;i++)
		{
			if(zi[i]=='?')
			{
				for(int j=0;j<26;j++)
				{
					if(vis[j]==0)
					{
						cout<<English[j];
						vis[j]=1;
						break;
					}
				}
			}
			else
			cout<<zi[i];
		}
		//cout<<endl;
	}
	else
	{
		cout<<-1;
	}
	return 0;
}

Problem3——咕咕东的奇妙序列

问题描述

在这里插入图片描述

问题分析

这道题主要是一个数学归纳问题,利用归纳方法我们会发现,在1 ~ 9数字一个占一位字符,10 ~ 99数字一个占两位以此类推。所以先算出是第几个这样的数(1 ~n),然后再算出是这个n中的第几个,然后得到该数是多少,再得到我们找的是这个数的第几位数,将这个数直接转化成string型,输出你要找的位数上的字符即可。
具体一些的操作就是,先用二分法去找到这个位数在于哪一个数上面,复杂度为log(n)*lg(n),首先先找到我们要求的数的位数,并顺便把它前面的数也算一遍,利用几位数的个数乘以其位数,即可。然后在找到位数后,进行计算其前面的数字个数,从而得到他的个数。

代码
#include<iostream>
using namespace std;
#include<cstdio>
#include<string>
#include<cmath>
int q;
long long k;
long long sum;
long long a,c,n,po;//之前的位数和    当前每个数字占的长度    当前位数的数字之和    位数                       
long long mid,ll,rr,ans,number; 
string shu;
int tot;
void wei(long long num)
{
	sum=0;
	a=0;
	c=0;
	n=0;
	po=1;
	while(true)
	{
		po=po*10;
		c=c+1;//每个数字的长度
		n=po-po/10;//当前位数 
		if(num>=po)//完全大于这个位数的数字
		{
			sum=sum+(a+c)*n+(n-1)*n/2*c;
			a=a+c*n;
		}
		else
		{
			n=num-po/10+1;
			sum=sum+(a+c)*n+(n-1)*n/2*c;
			a=a+c*n;
			break;
		}
		
	}
	
	
}
/*char shuzi(long long x,long long y)
{
	sum=0;
	a=0;
	c=0;
	n=0;
	pow=1;
	while(pow<=y)
	{
		pow=pow*10;
		c=c+1;//每个数字的长度
		n=pow-pow/10;
		a=a+c*n;
		if(a>=x)//完全大于这个位数的数字
		{
			a=a-c*n;
			n=x-a;
			sum=n/c;
			pow=pow/10;
			
			break;
		}
		
	}
	y=pow+n/c;
	shu=char(y*pow*10+y+1);
	cout<<shu;
	return shu[n%c+c-1];	
			
	
	
}*/
int main()
{
	scanf("%d",&q);
	for(int i=0;i<q;i++)
	{
		scanf("%lld",&k);
		ll=0;
		rr=1000000000;
		//cout<<"111"<<endl;
		while(ll<=rr)
		{
			mid=(ll+rr)>>1;
			//cout<<" mid="<<mid<<"    rr="<<rr<<"   ll="<<ll<<endl;
			wei(mid);
			//cout<<"ans="<<sum<<endl;
			if(sum>=k)
			{
				ans=mid;
				rr=mid-1;
				
			}
			else if(sum<k)
			{
				ll=mid+1;
			}
		}
		wei(ans-1);
		
		k=k-sum;
		//cout<<ans<<"    "<<k<<endl;
		ll=0;
		rr=ans+1;
		while(ll<=rr)
		{
			mid=(ll+rr)>>1;
			wei(mid);
			if(a>=k)
			{
				ans=mid;
				rr=mid-1;
			}
			else if(a<k)
			{
				ll=mid+1;
			}
		}
		wei(ans-1);
		k=k-a;
		//cout<<ans<<"    "<<k<<endl;
		//第ans个数的第k位
		//number=shuzi(k,ans);
		shu=to_string(ans);
		//cout<<shu<<endl;
		printf("%c\n", shu[k - 1]);//
	}
	
	
	
	return 0;
} 
遇到的问题

这个有些多,
1.没有搞清楚题意,骗分都没骗到,错误理解为输出的是整个数字而不是这个数字的某一位数
2.对于二分法没有掌握的十分确切,耗费了很多时间再调改二分法上面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值