【CSDN竞赛】第十四期解题报告

文章目录

  • 感想
      • 关于自己
      • 关于平台
  • 第一题 (难度:简单)
      • 题目描述
      • 100分做法
  • 第二题 (难度:简单+)
      • 题目描述
      • 100分做法
  • 第三题 (难度:中等)
      • 题目描述
      • 100分做法
  • 第四题(难度:中等)
      • 题目描述
      • 100分做法

这应该是站内相对详细的解题报告吧。
转载思路请@本人。

感想

关于自己

这一次出乎意料拿了第一,可能是别人没发挥好()。
题目感觉还行,难度适中。
有几个题目调了一段时间,还是调出来了。
由于本人要晚修,所以周三晚上那一场参加不了QAQ。
下次加油。

关于平台

题目听说可以自己出了?
如果可以,题目要怎么上传?质量如何确定?
这有待考察。
编程系统还是一如既往。
有个小问题:相同分数和做题时间的两个人要比总时间吗?这感觉没意义。
祝越来越好。

第一题 (难度:简单)

题目描述

对K个不同字符的全排列组成的数组, 面试官从中随机拿走了一个, 剩下的数组作为输入, 请帮忙找出这个被拿走的字符串?比如[“ABC”, “ACB”, “BAC”, “CAB”, “CBA”] 返回 “BCA

100分做法

这一题妥妥找规律。我们发现,当 K > 2 K>2 K>2时,全排列每一个位置的各个字母都出现了偶数次。
所以我们直接统计出每一位上哪个字母出现了奇数次,把这个字母输出即可。
听完是不是觉得豁然开朗?awa
C + + C++ C++代码如下:

#include
using namespace std;
int a[15][1005]={};
int t[105]={};
int n,X,Y;
int main()
{
	scanf("%d",&n);
	X=1;Y=1;
	while(n!=Y-1)
	{
		X++;
		Y*=X;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=X;j++)
		{
			char ch;
			cin>>ch;
			if(t[0]<X)t[++t[0]]=(int)(ch);//把出现过的字符记录
			a[j][int(ch)]^=1;//找奇数
		}
	}
	if(n==1)return 0*printf("%c%c",t[2],t[1]);//K=2
	for(int i=1;i<=X;i++)
	{
		for(int j=1;j<=t[0];j++)
		{
			if(a[i][t[j]]==1)
			{
				printf("%c",char(t[j]));//把奇数的输出
			}
		}
	}
}

第二题 (难度:简单+)

题目描述

已知棋盘大小为 n ∗ n n*n nn。 每个位置都有自己的权值 q q q。 该棋盘中有多少对行权值和小于列权值和。

100分做法

这一题是优化题,简单来说你需要优化你的代码使得时间复杂度达到最小。
有两种方法:

  1. 记录行列的前缀和。
  2. 记录矩阵的二维前缀和。

这里我们用第二种。
二维前缀和推导公式:
s u m i , j = a i , j + s u m i − 1 , j + s u m i , j − 1 − s u m i − 1 , j − 1 sum_{i,j}=a_{i,j}+sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1} sumi,j=ai,j+sumi1,j+sumi,j1sumi1,j1

其中 s u m i , j sum_{i,j} sumi,j表示 1 1 1 ~ i i i行中 1 1 1 ~ i i i列的数字和。式子用草稿纸画一下就知道了。
然后枚举行和列,用二位前缀和快速计算行列和,然后比较并统计答案。
C + + C++ C++代码如下:

#include
using namespace std;
int a[1005][1005]={};
int n;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%d",&a[i][j]);
			a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];//利用同一个数组省空间
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][n]-a[i-1][n]<a[n][j]-a[n][j-1])ans++;//统计答案,式子用草稿纸画一下就知道了
		}
	}
	printf("%d\n",ans);
	return 0;
}

第三题 (难度:中等)

题目描述

小Q的柠檬汁做完了。 掏出了自己的数字卡牌。 想要和别人做数字游戏。 可是她又不想要输掉游戏。 她制定好规则,每次每个人只能把这个牌换成它的因子的某个牌。 但是这个因子不能是1或者整数本身。 现在给出整数n。 两个人开始做游戏,谁无法再给出因子牌则该人胜利,如果该整数无因子牌直接视为先手胜利,请判断先手在最优策略状态下能否必胜。

100分做法

我们考虑这样几种情况:

  1. n ≤ 1 n\leq 1 n1,先手胜。
  2. n n n是质数,先手胜。
  3. n n n只有两个因子,则不管先手取哪个,后手都无法取,所以后手胜。
  4. n n n有多于两个因子(假设有 k k k个),先手可以取走 k − 2 k-2 k2个因子,然后转成情况 3 3 3,所以先手胜。

C + + C++ C++代码如下:

#include
using namespace std;
long long n;
int main()
{
	scanf("%lld",&n);
	int tot=0;
	for(int i=2;i<=10000000;i++)//分解质因子
	{
		while(n%i==0)
		{
			n/=i;
			tot++;
		}
	}
	if(n>1)tot++;//有大因子
	if(tot>2||tot<=1)tot=1;//先手胜
	else tot=2;//后手胜
	printf("%d",tot);
	return 0;
}

第四题(难度:中等)

题目描述

编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数字。 字母表中共有26个字母{a,b,…,z},这些特殊的单词长度不超过6且字母按升序排列。把所有这样的长度相同的单词放在一起,按字典顺序排列(a…z,ab…az,bc…bz…)一个单词的编码就对应着它在整个序列中的位置。 你的任务就是对所给的单词,求出它的编码。

100分做法

这一题看上去没什么好做法,怎么办呢?
搜索!哈哈
直接按顺序构造单词,然后当构造的与给出的相同,输出构造的次数(即位置)。
如果无法匹配,输出 0 0 0
构造方法:
长度依次递增,所有字母只出现一次,且字母升序。

C + + C++ C++代码如下:

#include
using namespace std;
char ch[105]={},a[105]={};
int bz[1005]={};
int len=0,qwq=0,tot=0;
void dfs(int x,char lst)
{
	if(x>qwq-1)
	{
		tot++;
		if(len+1!=qwq)return;
		for(int i=0;i<=len;i++)if(a[i]!=ch[i])return;
		printf("%d",tot);
		exit(0);
	}
	for(char i=lst;i<='z';i++)//lst保证升序
	{
		if(bz[int(i)]==0)//只出现一次
		{
			bz[int(i)]=1;
			a[x]=i;
			dfs(x+1,i+1);
			a[x]='\0';
			bz[int(i)]=0;
		}
	}
}
int main()
{
	cin>>ch;
	while(ch[len]>='a'&&ch[len]<='z'&&len<10)len++;
	len--;
	if(len+1>6)return 0*printf("0\n");//长度不超过6
	while(qwq<len+1)//长度从小到大
	{
		qwq++;
		dfs(0,'a');
	}
	printf("0");
	return 0;
}

你可能感兴趣的:(c++主要资料,考试,练习,算法,c++)