18.5.31测试总结

 (Rating总算回1500了……)


第一题

一道水题……

题意

描述:定义一个6位数是lucky的,当且仅当它的前3位之和等于后3位之和,比如165912。给出数x,找出最小的、大于x的幸运数字。无解输出-1

输入:一个数,表示x

输出:一个数,表示下一个幸运数字

范围:

样例输入:555555

样例输出:555564

正解

随便枚举一下就行了……

代码
#include<bits/stdc++.h>
using namespace std;
int x;
bool check(int k)
{
	int l=0,r=0;
	for(int i=1;i<=3;i++)
	{
		r+=k%10;
		k/=10;
	}
	for(int i=1;i<=3;i++)
	{
		l+=k%10;
		k/=10;
	}
	if(l==r)return 1;
	return 0;
}
int main()
{
	scanf("%d",&x);
	for(int i=x+1;i<=999999;i++)
		if(check(i)){printf("%d",i);return 0;}
	printf("-1");
	return 0;
}

第二题

T的特别惨,只拿到30……

题意

描述:有两个数组A,B,大小均为N。请在A中选择一个数x,B中选择一个数y,使得gcd(x,y)最大;如果有多组数gcd相同,找出x+y最大的

输入:第一行一个数n,第二行n个数表示Ai,第三行n个数表示Bi。

输出:输出gcd最大的那对数(gcd相同则和最大)的x+y的值。

范围:

样例输入:5     3 1 4 2 8     5 2 12 8 3

样例输出:16

我原来的思路是枚举,将两数组分别排序,再从大到小进行比较。我还加了一个剪枝,若这个数<maxgcd就可以break了,但是然并卵啊……n上限5e5直接爆炸……

正解

用bool数组存A、B,表示有这个数字(当然数组大小为Ai上限),顺便记录最大值(gcd不会超过这个最大值),再一个双重循环,外层枚举gcd(从大到小),内层枚举另一个因数,若在两数组内都有合法的数,则输出。

代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6;//这里得用Ai和Bi的上限了
int n,maxx=0,x;
bool a[N+10],b[N+10];
inline int read()
{  
	int N=0,C=1;
	char tf=getchar();
	while(tf<'0'||tf>'9'){if(tf=='-')C=-1;tf=getchar();}
	while(tf>='0'&&tf<='9')N=(N<<1)+(N<<3)+(tf^48),tf=getchar();
	return N*C;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)x=read(),a[x]=1,maxx=max(maxx,x);
	for(int i=1;i<=n;i++)x=read(),b[x]=1,maxx=max(maxx,x);
	for(int i=maxx;i>=1;i--)//gcd<=maxx;
	{
		int xx=0,yy=0;
		for(int j=1;j*i<=maxx;j++)
		{
			if(a[i*j])xx=i*j;
			if(b[i*j])yy=i*j;//gcd(xx,yy)=i;
		}
		if(xx&&yy){printf("%d",xx+yy);return 0;}
	}
	printf("1");
	return 0;
}

第三题

刷题量严重不足,没有看出来题目知识点……

题意

描述:商场有n件宝贝,每件宝贝有两个属性:价钱price和品牌brand。其中brand是1-5之间某个整数。每件宝贝价钱两两不同。有Q个代言人,每个代言人拍完戏之后,希望能从蓝月商场免费顺走一样宝贝。但是每个代言人有自己的喜好。具体来说,代言人会有d个喜欢的品牌(1 <= d <= 5),同时他最喜欢这些品牌中,价钱第k便宜的宝贝。请你求出每个代言人最喜欢的宝贝的价钱是多少!如果不存在这件宝贝,请输出-1。

输入:第一行一个整数n,第二行n个整数描述每件宝贝的品牌,第三行n个数描述每件宝贝的价钱。第四行一个整数Q,接下来Q*3行,每3行描述一个代言人的信息。其中第一行一个整数d,第二行d个数表示喜欢的品牌,第三行一个数表示k。

输出:一共Q行,每行一个数。

范围:

样例输入:3     1 1 2     1 3 2     3     1     1     2     2     1 2     2     1     3     1

样例输出:3     2     -1

(第一反应当然是暴力啦)

开五个数组分别存五种品牌的宝贝,用的时候挑出来汇总到一个大数组……

(然后就T了一半……)

正解

这题其实是一道状压题(并没有看出来……)f[i][j]表示i状态下第j便宜的宝贝价格,预处理过后查询十分快捷。

代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2,M=1<<5;
int n,q,m,k,like,brand;
int f[M][N];//状压+dp,f[i][j]表示i状态下第j便宜的宝贝价格 
struct item{int c/*价格*/,d/*品牌*/;}a[N];
inline int read()
{  
	int N=0,C=1;
	char tf=getchar();
	while(tf<'0'||tf>'9'){if(tf=='-')C=-1;tf=getchar();}
	while(tf>='0'&&tf<='9')N=(N<<1)+(N<<3)+(tf^48),tf=getchar();
	return N*C;
}
bool cmp(item x,item y){return x.c<y.c;}//按价格从小到大排 
int main()
{
	n=read();
	for(int i=1;i<=n;i++)a[i].d=read(),a[i].d=1<<(a[i].d-1);//状压 
	for(int i=1;i<=n;i++)a[i].c=read();
	sort(a+1,a+n+1,cmp);
	//预处理
	for(int i=1;i<M;i++)
		for(int j=1;j<=n;j++)
			if(a[j].d&i)//枚举子集 
				f[i][++f[i][0]]=a[j].c;//从小到大记录价格 
	//主程序
	q=read();
	for(int i=1;i<=q;i++)
	{
		m=read();
		like=0;
		for(int j=1;j<=m;j++)
		{
			brand=read();
			like|=1<<(brand-1);//此位变1 
		}
		k=read();
		if(k>f[like][0]/*like状态下不足k个宝贝*/)puts("-1");
		else printf("%d\n",f[like][k]);
	}
	return 0;
}

第四题

(骗分万岁)

这题估计是dp,但是我还是没有搞很懂……

题意

描述:有两个仅包含小写字母的字符串x,y,长度分别为n,m。你需要修改x串中某些字符,是的新的x串和y串的最长公共子序列长度至少为k。

      我们将’a’…’z’对应成0…25,修改两个字符付出的代价,为它们对应的数的xor值。比如说,将’a’修改成’z’代价为0 xor25=25。

      请问最少付出多少代价,使得新的x串和y串的LCS大于等于k。

输入:第一行三个数n,m,k,第二行长度为n的字符串x,第三行长度为m的字符串y。

输出:最小花费,如果不能请输出-1。(没错输出-1骗到10分……RP--)

范围:

样例输入:7 4 2     merging     pair

样例输出:3

正解

动态规划

f[i][j][p]表示A串的前i个和B串的前j个,LCS的长度至少为p时,最少花多少代价。

最后的答案就是f[n][m][k]。

要么不修改,要么改成和B串一样。

代码

(不存在的)

不是很懂,也只能看大佬的了……



第五题

第一眼看出是线段树问题,第二眼看出在我的能力范围之外……

知识没有巩固,现在只会敲模板题,像这题出现阶层这种奇怪的东西就凉凉了……

暴力骗了14……

正解十分玄学……

题意

描述:给出长度为n的序列A1,A2,…,An。进行m次操作,有三种类型:

        1、给出l,r,将区间[l,r]的Ai都加一。

        2、给出l,r,询问区间[l,r]的Ai!的和,对10^9取模。

        3、给出I,v,将Ai单点修改为v。

输入:第一行两个数n,m,第二行n个数Ai。接下来m行,每行三个数,第一个数k,表示第几类操作,后面两个数如题所述

输出:对于每个操作2输出解

范围:

样例输入:5 7     1 1 1 1 1     2 1 5     1 1 5     2 1 5     1 1 3     2 1 5     3 1 15     2 1 5

样例输出:5     10     22     674368016


正解

容易(疯狂打表)发现,如果一个数大于等于40,它的阶层%10^9就是0了……(怪我考试没有打表……)

然后在区间修改的时候,只需要把区间内小于40的数拿出来,进行单点+1,不然就根本不用改……

乍一看效率爆炸,然而一个数最多只能被修改50次,所以最多只有(n+q)*50次有效修改

只需用线段树维护区间内最小值的下标,每次单点修改

(一口老血)

代码

(不存在的)

第六题

还是线段树……还是不清楚……看到求和一脸懵逼……

于是果断暴力骗分……

本来这题小分很足(40),但是(手贱)没有用long long,就爆int了……

题意

描述:

输入:

输出:

范围:

输入样例:6 6     8 9 1 13 9 3     1 4 5     2 6 9     1 3 7     2 7 7     1 6 1     2 11 13

样例输出:45     19     21

正解


代码

(不存在的)

总结

后面三题还是没有弄很懂(基本来自老刘的题解)……代码等以后弄懂了再补吧……(还要补集训日记,上次保存的不知道怎么的就丢了……心态爆炸……假如生活欺骗了你

上次考试考的十分没有耐心,敲完会的就不想思考难题了,最后只A了前两题,后面全爆0……

这次难题也试着思考了,敲了敲也拿(骗)到了一些小分,终于没有上次考倒数的尴尬了……

所以思考很重要,就算题目难,好好想想还是可以拿(骗)到一部分分的……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值