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;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/80819790