链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
A---生不逢七
题目描述
睡前游戏中最简单又最好玩的游戏就是这个啦!
该游戏规则为:多名玩家轮流报数,当要报的数字中含有 7 或者是 7的倍数时(例如 37,49),不能将该数报出来,要换一种提前规定好的方式报数,当一个人报错或者报慢了这个人就输了。
我们认为玩家是围成一圈进行游戏的,第 n个人报完数之后,会轮到第 1个人报数。
现在告诉你玩家的总人数以及你上一个人报的数(用数字表示,即便这个数含有 7或者是 7 的倍数),你需要预测接下来 kkk 轮你要报的数字,当你需要报的数字含有 7或者是 7 的倍数时,你需要输出字符 p。
输入描述
第一行一个整数 T,表示输入数据的组数。 接下来每组数据中均只有一行数据,每行三个整数 n,a,k,分别表示玩家数量,你的上一位玩家报的数,你需要模拟的游戏轮数。 数据保证 1≤T,n,k,a≤100。
输出描述
共 T 行,每行输出 k个整数或者字符 p。
示例1
输入
3
2 16 3
3 69 3
2 1 10
输出
p 19 p
p p p
2 4 6 8 10 12 p 16 18 20
代码实现
#include<stdio.h>
#define N 10000
int judgeContain(int n){
int f=1,a;
while(n!=0){
a=n%10;
if(a==7){
f=0; //含有7
break;
}
n=n/10;
}
return f;
}
int judge(int n){
int f=1;
if(n%7==0){
f=0;
}
else if(judgeContain(n)==0){
f=0;
}
return f;
}
int main(){
int t,n,a,k;
scanf("%d",&t);
int num[N];
int i,j,h;
for(i=1;i<=t;i++){
scanf("%d%d%d",&n,&a,&k);
num[0]=a+1;
if(judge(num[0])==0){
num[0]=-1; //输出p
}
for(j=1;j<k;j++){
num[j]=a+1+j*n;
if(judge(num[j])==0){
num[j]=-1; //输出p
}
}
num[j]=0;
for(h=0;num[h+1]!=0;h++){
if(num[h]==-1){
printf("p ");
}
else {
printf("%d ",num[h]);
}
}
if(num[h]==-1){
printf("p\n");
}
else{
printf("%d\n",num[h]);
}
}
}
E---奏绝
题目描述
你拥有一个黑之章和白之章构成的序列,你可以用它进行演奏。
对于一次演奏的区间,如果这个区间的两个端点一个为黑之章,一个为白之章,那么该次演奏将会产生该区间长度的影响值,否则该次演奏影响值为 0。
区间长度定义为左端点到右端点的距离,比如 i 到 i+1 的距离为 1。
对于 m次询问,你要求出对于每次询问的区间,你在其所有子区间演奏的影响值的和,结果对 998244353取模。
输入描述:
第一行一个整数 n,m(1≤n,m≤2×105)。 接下来一行 01序列 ci(ci∈{0,1})表示黑之章白之章的排列顺序,其中 1表示黑之章,0表示白之章。 接下来 m 行,每行两个整数 l,r (1≤l≤r≤n),表示一次询问的区间。
输出描述:
m行,每行一个整数,表示对于每次询问的答案对 998244353取模。
示例1
输入
5 4
01001
1 3
2 5
3 4
1 5
输出
2
6
0
11
代码实现
//80%完成度,会出现段问题/运行超时
#include<stdio.h>
#include<string.h>
#define N 199990
int main(){
int n,m,q;
char s[N];
int i,sum,inf,j,k;
int a,b,c=0;
scanf("%d%d",&n,&m);
scanf("%s",&s);
for(k=0;k<m;k++){
sum=0;
scanf("%d%d",&a,&b);
for(i=a-1;i<b;i++){
for(j=i+1;j<b;j++){
if(s[i]!=s[j]){
inf=j-i;
sum+=inf;
}
}
}
sum=sum % 998244353;
printf("%d\n",sum);
}
}
运行超时问题
(-----当把N改小一些时,会出现段错误。)
由于使用了两层嵌套循环来计算每个查询区间内不匹配字符的数量,这导致算法的时间复杂度为O(m * n^2),其中m是查询的数量,n是字符串的长度。
D---幻兽帕鲁
题目描述
在幻兽帕鲁中,不同的帕鲁能干不同的工作,现在我们要对帕鲁进行分类以便他们能够更好的进行压榨。
你有 2^n 只帕鲁,初始给每只帕鲁一个工号,并让帕鲁按 [0,2^n-1] 工号的顺序排成一队。
当我们对区间 [l,r]的帕鲁进行操作时,我们会对该区间的帕鲁按顺序进行临时编号[0,r−l] ,记 mid=⌊(l+r)/2⌋,我们将临时编号为偶数和奇数的帕鲁,分别按顺序置于区间 [l,mid] 和 [mid+1,r],并递归对这两个区间进行上述操作,直到区间长度为 1 。
现在我们对 [0,2^n-1] 的幻兽进行一次操作,然后给你 m次询问,每次询问 x位置的帕鲁工号是多少?
输入描述:
第一行两个整数 n,m(0≤n≤60,1≤m≤105)。 接下来 m 行,每行一个整数 x表示询问第 x个位置的帕鲁的工号,位置从 0 开始计数。
输出描述:
输出每次询问的帕鲁的工号。
示例1
输入
2 4
0
1
2
3
输出
0
2
1
3
示例2
输入
3 4
0
2
5
7
输出
0
2
5
7
代码实现
//完成度50%----段错误问题
#include<stdio.h>
#define N 100000
void swap(int p[],int l,int r){
int mid=(l+r)/2;
int i,j,t,q[N];
for(i=0;i<=r-l;i++){
q[i]=p[l+i];
}
for(i=0;i<=r-l;i++){
if(i%2==0){
p[i/2+l]=q[i];
}
else{
p[mid+i/2+1]=q[i];
}
}
}
void recur(int p[],int l,int r){
if(l<r-1){
int mid=(l+r)/2;
swap(p,l,r);
recur(p,l,mid);
recur(p,mid+1,r);
}
}
int main(){
int n,m;
int x;
int p[N]={0};
int num=1;
int i,j;
scanf("%d%d",&n,&m);
for(j=1;j<=n;j++){
num=num*2;
}
for(j=0;j<num;j++){
p[j]=j;
}
recur(p,0,num-1);
for(i=0;i<m;i++){
scanf("%d",&x);
printf("%d\n",p[x]);
}
}
段错误
程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起。。。
方法二
完成度50%,依然是段错误
int main(){
int n,m;
long x;
scanf("%d%d",&n,&m);
while(m--){
scanf("%d",&x);
int res=0;
for(int i=n-1;i>=0;i--){
res+=((x>>i)&1)<<(n-1-i);
}
printf("%d\n",res);
}
}
依然存在段错误,暂时没找到什么解决方案。
但是用递归的方法运行时间会短一些。