2018/06/26测试

这是来自本蒟蒻的第一篇博客,各位大佬不要嫌弃QAQ

这篇博客主要是记录一下今天考的四道题(其实也是比较简单的四道题)

emmm,上题

 

1.求和(100/100)

【题目描述】

给定一连串正整数,依次由 1 个 1 ,2 个 2 ,3 个 3 ,……, 等组成,即1223334444……

现在给你两个正整数 A 和 B ,请你求出从第 A 个数到第 B 个数的和。

比如:A 是 1 ,B 是 3 ,则答案为:1+2+2=5。

【输入格式】

输入一行,包括正整数 A 和 B(1≤A≤B≤1000)。

【输出格式】

输出一个正整数,为从第 A 个数到第 B 个数的和。

【样例数据1】

输入
1 3

输出
5

【样例数据2】

输入
3 7

输出
15

分析:第一题比较简单,先用循环生成数列,再求和(但是我才不会告诉你我因为某种不知名的原因卡了半个多小时)

#include<cstdio>
#include<cstring>
using namespace std;
int a[1005];
int main()
{
	int x,y,i,j,k,ans;       //x是A,y是B 
	scanf("%d%d",&x,&y);
	i=1;
	k=0;
	while(k<y)               //求这个数列 
	{
		for(j=1;j<=i;++j)
		  a[k+j]=i;
		k+=i;
		i++;
	}
	ans=0;
	for(i=x;i<=y;++i)        //求和 
	  ans+=a[i];
	printf("%d",ans);
	return 0;
}

 

2.生成字符串(60/100)

【题目描述】

我们规定本题涉及的字符串只由字符“0”、“1”、“*”组成,其中字符“*”表示该字符可由字符“0”或“1”替代。
现有一些固定长度的字符串,根据这些字符串生成所有可生成的相同长度的不重复的字符串。如:
{ 10,*1,0* } 可生成 { 10,01,11,00 }
{ 101,001,*01 } 可生成 { 101,001 }
注意后一个例子中“*01”并没有生成新的字符串。

【输入格式】

第一行是两个整数 m,n(1≤m≤15;1≤n≤2500)。m 表示字符串的长度,n 表示字符串的个数。
接下来以下 n 行,每行各有一个字符串。
文件中各行的行首、行末没有多余的空格。 

【输出格式】

输出一个整数,表示所能生成的字符串的个数。 

【样例数据】

输入
2 3
10
*1
0*

输出
4

分析:对于每一个字符串,因为只出现了0和1(*可以看做是0或者1),可以把它看做多位的二进制编码,那么我们就可以把它转换成十进制下的数(例如1001=1*2^3+0*2^2+0*2^1+1*2^0=9),就可以用一个数组来记录这个字符串是否出现过,数组的最大下标应为111111111111111(15个1)的十进制数32767,接下来就用搜索来做

#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
char s[20],ans[20];          //s为原字符串,ans为将*替换成0或1后的字符串 
int a[32768];                //数组下标最大值为32767 
void change()                //将字符串转换为它的十进制数 
{
	int i,k=1,r=0;
	for(i=m;i>=1;--i)
	{
		r+=(ans[i]-'0')*k;
		k*=2;
	}
	a[r]++;                  //统计这个字符串出现的次数 
}
void search(int x)           //x是处理到了第x位 
{
	if(x==m+1)               //若找到一个符合条件的字符串 
	{
		change();            //将它转换成十进制数 
		return;
	}
	if(s[x]!='*')            //若s[x]不是*,则ans[x]=s[x] 
	{
		ans[x]=s[x];
		search(x+1);
	}
	else                     //若s[x]是*,则ans[x]=0或1 
	{
		ans[x]='0';
		search(x+1);
		ans[x]='1';
		search(x+1);
	}
}
int main()
{
	int i,ans=0;
	scanf("%d%d",&m,&n);
	for(i=1;i<=n;++i)
	{
		scanf("%s",s+1);
		search(0);
	}
	for(i=0;i<=32767;++i)    //统计不同字符串的个数 
	  if(a[i]>0)
	    ans++;
	printf("%d",ans);
	return 0;
}

 

3.跳格子(70/100)

 

【题目描述】

Tom 现在已经成为一个游戏里的重要人物。
这个游戏界面包含一行 N 个方格,N 个方格用 1 到 N 的数字表示。Tom 开始是在 1 号位置,然后能够跳到其他的位置,Tom 的第一跳必须跳到 2 号位置。随后的每一跳必须满足两个条件:
1、如果是向前跳,必须比前面一跳多跳一个方格。
2、如果是向后跳,必须和前面一跳一样远。
比如,在第一跳之后(当在2号位置时),Tom 能够跳回 1 号位置,或者向前跳到 4 号位置。
每次他跳入一个位置,Tom 必须付相应的费用。Tom 的目标是从一号位置尽可能便宜地跳到 N 号位置。
请你写一个程序,看看 Tom 跳到 N 号位置时需要的最少花费是多少。

【输入格式】

输入共有 N+1 行。
第 1 行:包含一个整数 N(2≤N≤1000),它是位置的数量。
第 2..N+1 行:第 i+1 行表示第 i 个方格的费用,是一个正整数(不超过500)。

【输出格式】

输出一个整数,表示 Tom 跳到 N 号位置时需要的最少花费。

【样例数据1】

输入
6
1
2
3
4
5
6

输出
12

 

【样例数据2】

输入
8
2
3
4
3
1
6
1
4

输出
14

分析:这是一道动态规划的题,我们可以用f[i][j]来表示当前位于第i个格子,上次跳了j步的最小代价

若是从上个格子往前跳到当前第i格:f[i][j]=min(f[i][j],f[i-j][j-1]+cost[i]);

若是从上个格子往后跳到当前第i格:f[i][j]=min(f[i][j],f[i+j][j]+cost[i]);

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long oo=2e+9;
int cost[1005],f[1005][1005];
int main()
{
	int n,i,j,minn=oo;
	scanf("%d",&n);
	for(i=1;i<=n;++i)
	  scanf("%d",&cost[i]);
	memset(f,0x3f,sizeof(f));
	f[1][0]=0;
	for(i=1;i<=n;++i)
	{
		for(j=i+1;j<=n;++j)
		  f[j][i]=min(f[j][i],f[j-i][i-1]+cost[j]);
		for(j=n-i;j>=1;--j)
		  f[j][i]=min(f[j][i],f[i+j][i]+cost[j]);
	}
	for(i=1;i<=n;++i)
	  minn=min(minn,f[n][i]);
	printf("%d",minn);
	return 0;
}

 

4.Grid(0/100)

 

【题目描述】

有一个 2×N 的矩阵,矩阵的每个位置上都是一个英文小写字符。
现在需要从某一个位置开始,每次可以移动到一个没有到过的相邻位置,即从 (i,j) 可以移动到 (i-1,j)(i+1,j)(i,j-1)(i,j+1) (要求该位置在矩阵上且之前没有到过)。
从选取的起点开始,经过 2N-1 次移动后,将会走过矩阵的每一个位置,将移动经过的格子依次取出来就得到了一个长度为 2N 的串。
可以任意选择起点和终点,任意选择移动方案,求能得到多少种不同的串。

【输入格式】

第一行,一个正整数 N 。
接下来两行,每行一个由英文小写字符组成的字符串,描述这个矩阵。

【输出格式】

输出一行一个整数,表示能得到的串的总数。

【样例数据1】

输入
1
a
a

输出
1

 

【样例数据2】

输入
3
dab
abd

输出
8

 

【样例数据3】

输入
5
ababa
babab

输出
2

【样例解释2】

能得到的字符串有:abdbad, adabdb, badabd, bdbada, dababd, dabdba, dbabad, dbadab

【数据规模与约定】
对于20%的数据,N≤5。
对于60%的数据,N≤50。
对于100%的数据,N≤600。

分析:有效的走法实际上只有一种(通过翻转需要计算四种情况)

        

首先枚举一个起点,设上图中左端红色开端为起点,从起点开始一直到与绿线相接的路径是一定要走的,接下来绿线的方向也是固定的,不过长度需要枚举,当绿线停止时,剩下的红线也是固定的

为了对字符串进行计数,将路径上得到的字符串进行哈希,红色部分是可以预处理得到的,绿色部分可以依次枚举计算,这样只需要每次对三个串的哈希值进行拼接就可以了

(这道题我暴力都没有打出来QAQ)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t=0;
int h=2333;
int H=2333333;
char s[5][605];
int first[2400000],next[6000005];
unsigned long long now,l[5][1205],pow[1205],num[6000005];
void add(unsigned long long x)
{
	int i,y=x%H;
	for(i=first[y];i;i=next[i])
	  if(num[i]==x)
	    return;
	t++;
	num[t]=x;
	next[t]=first[y];
	first[y]=t;
}
int main()
{
	int n,m,i,j,k;
	scanf("%d",&n);
	for(i=1;i<=2;++i)
	  scanf("%s",s[i]+1);
	pow[0]=1;
	for(i=1;i<=1200;++i)
	  pow[i]=pow[i-1]*h;
	for(m=1;m<=4;++m)
	{
		for(i=1;i<=n;++i)
		{
			l[1][i]=0;
			l[2][i]=0;
			for(j=i;j>=1;--j)  l[1][i]=l[1][i]*h+s[1][j];
			for(j=1;j<=i;++j)  l[1][i]=l[1][i]*h+s[2][j];
			for(j=i;j>=1;--j)  l[2][i]=l[2][i]*h+s[2][j];
			for(j=1;j<=i;++j)  l[2][i]=l[2][i]*h+s[1][j];
		}
		for(i=1;i<=n;++i)
		{
			now=0;
			for(j=i;j<=n;++j)  now=now*h+s[1][j];
			for(j=n;j>=i;--j)  now=now*h+s[2][j];
			k=2;
			for(j=i;j>=1;--j)
			{
				add(l[k][j-1]+now*pow[2*(j-1)]);
				now=now*h+s[k][j-1];
				k=3-k;
				now=now*h+s[k][j-1];
			}
		}
		for(i=1;i<=n;++i)  swap(s[1][i],s[2][i]);
		if(m==2)
		{
			for(i=1;i<=n/2;++i)
			{
            	                swap(s[1][n-i+1],s[1][i]);
                                swap(s[2][n-i+1],s[2][i]);
                        }
		}
	}
	printf("%d",t);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值