ACM---牛客小白月赛93

链接:登录—专业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]);
    }
}

段错误

程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起。。。

方法二

参考:http://t.csdnimg.cn/bLIQu

完成度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);
    }
}

依然存在段错误,暂时没找到什么解决方案。

但是用递归的方法运行时间会短一些。

  • 43
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值