这是来自本蒟蒻的第一篇博客,各位大佬不要嫌弃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;
}