第五届传智杯-初赛【C组-题解】

A题

题目背景

在宇宙射线的轰击下,莲子电脑里的一些她自己预定义的函数被损坏了。

对于一名理科生来说,各种软件在学习和研究中是非常重要的。为了尽快恢复她电脑上的软件的正常使用,她需要尽快地重新编写这么一些函数。

你只需输出fun(a,b) 的值。

输入格式

  • 共一行两个整数 a,b。

输出格式

  • 共一行一个整数 fun(a,b) 的值。

输入输出样例

 

 题解:

签到题:首先用if 语句判断 b 的符号,然后加在 a 的绝对值上即可。

参考代码 

版本 1:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
int main(){
    int a, b;
    cin >> a >> b;
    cout << fixed << setprecision(0) << copysignl(a, b) + 1e-9 << endl;
    return 0;
}

版本 2:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
int main(){
    i64 a, b; cin >> a >> b;
    cout << (b < 0 ? -llabs(a) : llabs(a));
    return 0;
}

版本3:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int a,b;
    cin >> a >> b;
    if (b>0 && a==INT_MIN)
        cout << 2147483648ll << endl;
    else
    {
        a=abs(a);
        if (b<0)
            a*=-1;
        cout << a << endl;
    }
    return 0;
}

版本4:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long a = scanner.nextLong(), b = scanner.nextLong();
        System.out.println((Math.abs(a) * (b > 0 ? 1 : -1)));
    }
}

B题:

题目背景

【题目背景和题目描述的两个题面是完全等价的,您可以选择阅读其中一部分。】

专攻超统一物理学的莲子,对机械结构的运动颇有了解。如下图所示,是一个三进制加法计算器的(超简化)示意图。

初始时齿轮的状态如上。

 

把第一个齿轮拨动一个单位长度,变为如上图所示。 

 

 题解:

模拟题。按照题目要求输入整数 a,b,模拟这个奇怪的进位规则即可。

参考代码 

 版本 1:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
int qread(){
    int w=1,c,ret;
    while((c = getchar()) >  '9' || c <  '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    return ret * w;
}
const int MAXN = 2e5 + 3;
int A[MAXN], B[MAXN];
int main(){
    int n = qread(), m = qread(), l = max(n, m);
    dn(n, 1, i) A[i] = qread();
    dn(m, 1, i) B[i] = qread();
    up(1, l, i) A[i] += B[i], A[i + 1] += A[i] / (i + 1), A[i] %= i + 1;
    if(A[l + 1]) ++ l;
    dn(l, 1, i) printf("%d%c", A[i], " \n"[i == 1]);
    return 0;
}

版本2:

#include <bits/stdc++.h>
using namespace std;
int a[200050],b[200050];
int main()
{
    auto read=([&]{
        int x;cin >> x;
        return x;
    });
    int n=read(),m=read();
    int len=max(n,m)+1;
    generate_n(a+1,n,read);
    generate_n(b+1,m,read);
    reverse(a+1,a+n+1);
    reverse(b+1,b+m+1);
    for (int i=1;i<=len;i++)
    {
        a[i]+=b[i];
        a[i+1]+=(a[i]/(i+1));
        a[i]%=(i+1);
    }
    while (a[len]==0 && len>1)
        len--;
    reverse(a+1,a+len+1);
    for (int i=1;i<=len;i++)
        cout << a[i] << " ";
    return 0;
}

版本3:

import java.util.Scanner;

public class Main {

    public static int[] a = new int[200005];
    public static int[] b = new int[200005];
    public static int[] c = new int[200005];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(), m = scanner.nextInt();
        int maxLength = Math.max(n, m);
        for (int i = (maxLength - n) + 1; i <= maxLength; ++i)
            a[i] = scanner.nextInt();
        for (int i = (maxLength - m) + 1; i <= maxLength; ++i)
            b[i] = scanner.nextInt();
        for (int i = maxLength, cnt = 2; i > 0; --i, ++cnt) {
            c[i] += a[i] + b[i];
            if (c[i] >= cnt) {
                c[i] -= cnt;
                c[i - 1] += 1;
            }
        }
        if (c[0] > 0) {
            System.out.printf("%d ", c[0]);
        }
        for (int i = 1; i <= maxLength; ++i) {
            System.out.printf("%d ", c[i]);
        }
        System.out.println();
    }
}

 C题

题目背景

你现在不能休息,周围有 deadline 在游荡。

莲子正在赶自己的程序设计作业。除了完成程序代码的编写,对提交上去的作业进行排版以对助教留下良好印象同样重要。

而众所周知,文章里面的代码和一些特殊性质的文本是要附上行号的,然而它们的篇幅往往都很长,手动去加容易出现失误。因此,莲子决定自力更生造轮子,写一个行号生成器。

输入格式

输入包含若干行,为原始的文本文件。

输出格式

输出包含若干行,为加上行号后的文本文件。

输入输出样例

题解:

参考代码 

版本1:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
const int MAXN= 2e4 + 3;
char S[MAXN], c; int l, m;
int main(){
    m = count(S + 1 , S + 1 + fread(S + 1, 1, MAXN, stdin), '\n');
    int s = log10(m) + 1 + 1e-9, p = 0;
    up(1, m, i){
        int t = log10(i) + 1 + 1e-9;
        for(int j = 1;j <= s - t;++ j) putchar( ' '); printf("%d ", i);
        for(p = p + 1;S[p] != 10;++ p) putchar(S[p]); putchar('\n');
    }
    return 0;
}

版本2:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
char buf[200050];
vector <char> s[200050];
int cnt;
int get_digit(int x)
{
    int digit=1,ret=1;
    while (ret<=x)
    {
        digit++;
        ret*=10;
    }
    return digit;
}
int main()
{
    while(fgets(buf,200000,stdin)!=NULL)
    {
        cnt++;
        for (int i=0;buf[i]!='\n';i++)
            s[cnt].push_back(buf[i]);
    }
    int cnt_digit=get_digit(cnt);
    for (int i=1;i<=cnt;i++)
    {
        for (int j=1;j<=cnt_digit-get_digit(i);j++)
            putchar(' ');
        cout << i << ' ';
        for (int j=0;j<s[i].size();j++)
            putchar(s[i][j]);
        putchar('\n');
    }
    return 0;
}

版本3: 

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;

public class Main {

    public static List<String> list = new ArrayList<>();

    public static int getBit(int x) {
        int cnt = 0;
        while (x > 0) {
            x /= 10;
            ++cnt;
        }
        return cnt;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            list.add(scanner.nextLine());
        }
        int size = list.size();
        int len = getBit(size);
        for (int i = 0; i < size; ++i) {
            System.out.printf("%" + len + "d %s\n", i + 1, list.get(i));
        }
    }
}

D题:

题目背景

莲子正在研究分子的运动。

每个分子都有一个速度,约定正方向为正,负方向为负。分子的数量极多,速度又并不一致,看上去杂乱无章。于是莲子希望调整部分分子的速度,使得最终分子们看上去整齐。

 题解:

参考代码 

版本1:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
int qread(){
    int w=1,c,ret;
    while((c = getchar()) >  '9' || c <  '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    return ret * w;
}
const int MAXN = 1e5 + 3;
int A[MAXN], ans = INF;
int main(){
    int n = qread(), m = qread();
    up(1, n, i) A[i] = qread();
    sort(A + 1, A + 1 + n);
    int j = 1;
    up(1, min(n, m + 1), i){
        j = max(i, j);
        while((i - 1) + (n - j) + min(i - 1, n - j) > m) ++ j;
        ans = min(ans, A[j] - A[i]);
    }
    printf("%d\n", ans);
    return 0;
}

版本2:

import java.util.Scanner;
import java.util.Arrays;

public class Main {

    public static int[] a = new int[100005];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(), m = scanner.nextInt();
        for (int i = 1; i <= n; ++i)
            a[i] = scanner.nextInt();
        Arrays.sort(a, 1, n + 1);
        int j = 1, ans = Integer.MAX_VALUE;
        for (int i = 1; i <= Math.min(n, m + 1); ++i) {
            j = Math.max(j, i);
            while((i - 1) + (n - j) + Math.min(i - 1, n - j) > m) 
                ++j;
            ans = Math.min(ans, a[j] - a[i]);
        }
        System.out.println(ans);
    }
}

E题:

题目背景

梅莉这个学期选修了经济学。但是主修心理学的她实在不擅长经济领域的分析,为此她时常抱怨自己学不会,想退课。

但是如果现在退掉的话这学期的学分就不够啦,因此她根据“梦中”的经历,“胡诌”了一个简单到不现实的市场模型,并依据这个模型编起了 essay。为了方便地编出图表,她需要写一个程序来查询每个时刻的市场贸易差。

 题解

 参考代码

版本1:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
i64 qread(){
    i64 w=1,c,ret;
    while((c = getchar()) >  '9' || c <  '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    return ret * w;
}
i64 val(i64 p){return 2 * p * p - p;}
int main(){
    up(1, qread(), TTT){
        i64 k = qread(), p = 0;
        dn(30, 0, i){
            if(val(p | 1 << i) < k) p |= 1 << i;
        }
        int i = p + 1, w = i - 1;
        i64 l = val(p) + 1, ll = l + w;
        i64 r = val(i),     rr = r - w;
        if(l  <= k && k <  ll) printf("%lld\n", k - l     ); else 
        if(ll <= k && k <= rr) printf("%lld\n", w - k + ll); else 
            printf("%lld\n", k - r);
    }
    return 0;
}

版本2:

#include <iostream>
using namespace std;
int main()
{
    int q;
    cin >> q;
    while (q--)
    {
        long long k,l=1,r=2e9,ans=0;
        cin >> k;
        while (l<=r)
        {
            long long mid=(l+r)/2;
            if ((long long)mid*mid*2-mid>=k)
            {
                r=mid-1;
                ans=mid;
            }
            else
                l=mid+1;
        }
        ans--;
        long long len=ans*ans*2-ans;
        k-=len+1;
        if (k<=ans)
            cout << k << endl;
        else if (k<=3*ans)
            cout << 2*ans-k << endl;
        else
            cout << -4*ans+k << endl;

    }
    return 0;
}

版本3:

import java.io.*;
import java.util.StringTokenizer;

public class Main {

    public static long val(long p) {
        return p * 2 * p - p;
    }

    public static class Scanner {
        public BufferedReader in;
        public StringTokenizer tok;
        public String next() { hasNext(); return tok.nextToken(); }
        public String nextLine() { try { return in.readLine(); } catch (Exception e) { return null; } }
        public long nextLong() { return Long.parseLong(next()); }
        public int nextInt() { return Integer.parseInt(next()); }
        public PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        public boolean hasNext() {
            while (tok == null || !tok.hasMoreTokens()) try { tok = new StringTokenizer(in.readLine()); } catch (Exception e) { return false; }
            return true;
        }
        public Scanner(InputStream inputStream) { in = new BufferedReader(new InputStreamReader(inputStream)); }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int q = scanner.nextInt();
        while (q-- > 0) {
            long k = scanner.nextLong(), p = 0;
            for (int i = 30; i >= 0; --i) {
                if (val(p | 1 << i) < k)
                    p |= 1 << i;
            }
            long i = p + 1, w = i - 1;
            long l = val(p) + 1, ll = l + w;
            long r = val(i), rr = r - w;
            if (l <= k && k < ll)
                System.out.println(k - l);
            else if (ll <= k && k <= rr)
                System.out.println(w - k + ll);
            else
                System.out.println(k - r);
        }
    }
}

 F题

作为大学生,莲子和梅莉有着比高中时更为闲暇的课余时光。在没有课的时候,她们喜欢玩大富翁这一游戏,在游玩过程中交流自己的喜怒哀乐。

 输入输出样例

题解

模拟题。没什么好说的。这里就讲几个细节:

参考代码 

 版本1:

#include<bits/stdc++.h>
#define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
#define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
using namespace std;
typedef long long i64;
const int INF = 2147483647;
int qread(){
    int w=1,c,ret;
    while((c = getchar()) >  '9' || c <  '0') w = (c == '-' ? -1 : 1); ret = c - '0';
    while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
    return ret * w;
}
int n, m, q, maxl; bool o = 1;
const int MAXN = 100 + 3;
int C[MAXN][MAXN], A[MAXN], D[MAXN], L[MAXN], O[3], T[MAXN];
i64 M[2];
int main(){
    n = qread(), m = qread(), q = qread(), maxl = qread();
    M[0] = M[1] = m, O[0] = O[1] = 1;
    up(1, n, i) L[i] = 0, T[i] = -1;
    up(1, n, i)
        up(0, maxl - 1, j) C[i][j] = qread();
    up(1, n, i) D[i] = qread();
    for(int op, k;~scanf("%d%d", &op, &k);){
        if(op == 1){
            if(o == 1){
                up(1, n, i) if(T[i] != -1) M[T[i]] += D[i];
            }
            o ^= 1;
            up(1, k, i){
                O[o] = (O[o]) % n + 1;
                int p = O[o];
                if(T[p] ==  o) M[o] += A[p]; else 
                if(T[p] == !o){
                    M[!o] += A[p], M[o] -= A[p];
                    if(M[o] < 0)
                        puts(o ? "Merry" : "Renko"), exit(0);
                }
            }
        } else {
            int p = O[o];
            while(k && L[p] < maxl && M[o] >= C[p][L[p]] && T[p] != !o){
                A[p] += C[p][L[p]], M[o] -= C[p][L[p]];
                ++ L[p], T[p] = o, -- k;
            }
        }
    }
    up(1, n, i) if(T[i] != -1) M[T[i]] += D[i];
    printf("%lld %lld\n", M[0], M[1]);
    return 0;
}

版本2:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <queue>

using namespace std;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}

int n,m,q,L,C[105][105],d[105],a[105],lv[105],pos[2],belong[105];

long long money[2];

const string name[2]={"Renko","Merry"};

inline void putfail(int id)
{
    cout << name[id] << endl;
    exit(0);
}

inline void forward(int id,int k)
{
    for (int i=1;i<=k;i++)
    {
        int &p=pos[id];
        p++;
        if (p>n)
            p-=n;
        if (belong[p]==id)
            money[id]+=a[p];
        else if (belong[p]==(id^1))
        {
            money[id]-=a[p];
            money[id^1]+=a[p];
        }
        if (money[id]<0)
            putfail(id);
    }
}

inline void build(int id,int k)
{
    int p=pos[id],cost=C[p][lv[p]];
    for (int i=1;(money[id]>=cost && lv[p]<L && (belong[p]==-1 || belong[p]==id) && i<=k);i++)
    {
        belong[p]=id;
        money[id]-=cost;
        a[p]+=cost;
        cost=C[p][++lv[p]];
    }
}

int main()
{
    n=read(),m=read(),q=read(),L=read();
    for (int i=1;i<=n;i++)
    {
        for (int j=0;j<L;j++)
            C[i][j]=read();
    }
    for (int i=1;i<=n;i++)
        d[i]=read();
    pos[0]=pos[1]=1;
    fill(belong+1,belong+n+1,-1);
    money[0]=money[1]=m;
    for (int i=0;i<2*q;i++)
    {
        int op=read();
        begin:
        for (int j=1;j<=n && !(i&1);j++)
        {
            if (belong[j]==0)
                money[0]+=d[j];
            else if (belong[j]==1)
                money[1]+=d[j];
        }
        int k=read();
        forward(i&1,k);
        if (i==2*q-1)
            break;
        op=read();
        if (op==1)
        {
            i++;
            goto begin;
        }
        else
        {
            k=read();
            build(i&1,k);
        }
    }

    for (int j=1;j<=n;j++)
    {
        if (belong[j]==0)
            money[0]+=d[j];
        else if (belong[j]==1)
            money[1]+=d[j];
    }

    cout << money[0] << " " << money[1] << endl;
    return 0;
}

💖 喜欢我的文章,记得点赞👍+评论💬+收藏⭐️+关注😙の,你的反馈就是我不断更新的动力!

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值