题目121:分糖果
作者: xxx

时间限制: 10s

章节: 一维数组

问题描述
肖恩和帕特里克是兄弟,他们从他们的父母那里得到了很多糖果。每一块糖具有一个正整数的价值,孩子们希望分他们得到的糖果。首先,肖恩将这些糖果分成两堆,并选择一堆给帕特里克。然后,帕特里克将尝试计算每堆的价值,其中每堆的价值是那堆糖果价值的总和,如果他觉得没有平等的价值,他将开始哭了起来。

不幸的是,帕特里克太小了,所以不能正确的计算。他只会二进制无进位的加法。比如说,他想算12(二进制为1100)加5(二进制为101),他会把最右边的两位加法算正确,但是第三位会忘记进位。(即0+0=0,0+1=1,1+0=1,1+1=0)

因此,帕特里克算12加5的结果为9。下面几个是帕特里克算的结果:

5 + 4 = 1

7 + 9 = 14

50 + 10 = 56

肖恩数学很好,他想得到价值总和更高的糖果并且不让他的弟弟哭。如果可能,他会分成两个非空的糖果袋,让帕特里克认为,双方都有相同的值的糖果。给你每一袋糖果每一块糖果的价值,我们想知道是否可能让帕特里克相信他们得到糖果价值的总量是相同的。如果可能计算出肖恩能得到的最大的价值。

输入说明
第一行输入T(1<T<10),表示接下来输入T组测试数据。

每组测试数据占一行,每行包含以下数据,N C1 C2 .. Cn(其中N(2 ≤ N ≤ 10)代表从父母那里得到糖果的总数,C(1 ≤ Ci ≤ 100)代表每块糖果的价值)

输出说明
若不能输出NO,若能则输出肖恩得到的最大的价值。

总结:
1. 弟弟的计算为异或运算,弟弟觉得公平的情况为两堆糖果的异或值相等,即这两队糖果的异或值异或结果为0,即整堆糖果的异或值为0,此时将糖果价值最小的一颗为一堆,其他糖果为一堆,则肖恩得到的最大的价值

2. C语言中异或运算用 ^ 实现,对每堆糖果,计算正确的总价值及异或值,;遍历完每颗糖果,若这堆糖果异或值不为0,则这堆糖果帕特里克不相信他们得到糖果价值的总量相同;若异或值为0,找到价值最小的给帕特里克,用总价值 - 最小的价值即为肖恩得到的最大的价值

#include <stdio.h>
int main() {
    int t;
    scanf("%d", &t);
    for(int i = 0; i < t; i++){
        int n;
        scanf("%d", &n);
        int arr[10];
        int total_xor = 0;
        int total_sum = 0;
        int min_val = 101;  //糖果价值最大为100
        for(int j = 0; j < n; j++){
            scanf("%d", &arr[j]);
            total_sum += arr[j];//正确价值
            total_xor ^= arr[j];//帕特里克算
            if(arr[j] < min_val){
                min_val = arr[j];
            }
        }
        if(total_xor != 0)
            printf("NO\n");
        else
            printf("%d\n", total_sum - min_val);
    }
    return 0;
}
 

题目122:循环数
作者: xxx

时间限制: 1s

章节: 一维数组

问题描述
循环数是那些不包括0这个数字的没有重复数字的整数 (比如说, 81362) 并且同时具有一个有趣的性质, 就像这个例子:

如果你从最左边的数字( 记为n,在这个例子中是8) 开始往右边数,一直数n个数字(如果已经到了最右边则回到最左边),你会停在另一个不同的数字上。如果停在一个相同的数字上,这个数就不是循环数。

就像: 8 1 3 6 2 从最左边接下去数8个数字: 1 3 6 2 8 1 3 6 所以下一个数字是6. 重复这样做 (这次从'6'开始数6个数字) 并且你会停止在一个新的数字上: 2 8 1 3 6 2, 也就是2. 再这样做 (这次数两个): 8 1。 再一次 (这次数一个): 3。 又一次: 6 2 8, 这时你回到了起点。

此时,我们数到的数字依次是:8 6 2 1 3,即每一个数字都被数了1次,并且回到了起点。

如果你将每一个数字都数了1次以后没有回到起点, 你的数字不是一个循环数。

给你一个数字 M (在1到9位之间), 找出第一个比 M大的循环数(输入的M保证这个循环数能保存在4位的有符号整数中)。

输入说明
仅仅一行, 包括M

输出说明
仅仅一行,包括第一个比M大的循环数。

总结:
1. is_circular() 判断一个数是否为循环数,将该数用字符串存储,首先判断该数的每个数字是否有0,有0不为循环数;随后检查该数的每位数是否都不一样,若有一样的数则该数不为循环数;判断完这两个条件之后开始循环

2. visited[] 记录每个位置是否被访问,current 记录当前位置,visited_count 记录已访问的位数个数;对于每次循环,首先访问当前起点,visited[current] = 1,visited_count++,计算当前要走的步数 steps = str[current] - '0',令 current 指向走完后的位置 current = (current + steps) % len;一个数为循环数的条件为每个位置都被访问且访问的个数为数的长度

#include <stdio.h>
#include <string.h>
//是否是循环数
int is_circular(int num){
    char str[20];
    sprintf(str, "%d", num);
    int len = strlen(str);
    //检查是否包含0
    for (int i = 0; i < len; i++) {
        if(str[i] == '0')
            return 0;
    }
    //检查是否有重复数字
    int digits[10] = {0};
    for(int i = 0; i < len; i++){
        int digit = str[i] - '0';
        if(digits[digit] != 0)
            return 0;  //有重复
        digits[digit] = 1;
    }
    //模拟循环过程
    int visited[20] = {0};  //记录每个位置是否被访问过
    int current = 0;  //当前位置
    int visited_count = 0;
    while(1){
        if(visited[current]){
            //如果访问过这个位置
            if(current == 0 && visited_count == len){
                //回到起点且所有位置都访问过
                return 1;
            }
            else{
                //重复访问但条件不满足
                return 0;
            }
        }
        visited[current] = 1;
        visited_count++;
        //计算要走的步数
        int steps = str[current] - '0';
        //移动当前位置
        current = (current + steps) % len;
    }
    return 0;
}
int main(){
    int m;
    scanf("%d", &m);
    int num = m + 1;
    while(1){
        if(is_circular(num)){
            printf("%d\n", num);
            break;
        }
        num++;
    }
    return 0;
}
 

题目124:分数化小数
作者: xxx

时间限制: 1s

章节: 字符串

问题描述
写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。

如果小数有循环节的话,把循环节放在一对圆括号中。

例如, 1/3 = .33333333 写成0.(3) 

41/333 = 0.123123123... 写成0.(123) 

用xxx.0 表示整数

典型的转化例子: 1/3 = 0.(3) 

22/5 = 4.4 

1/7 = 0.(142857) 

2/2 = 1.0 

3/8 = 0.375 

45/56 = 0.803(571428)

输入说明
单独的一行包括被空格分开的 N和D, 1 <= N,D <= 100000。

输出说明
小数的表示方法上面说的很明白了,如果输出的长度超过76个字符,每行输出76个字符(包括小数点、括号等)。

总结:
1. 首先计算整数部分,若余数为0,直接输出,若余数不为0开始求小数部分

2. remainder_pos[]:记录每个余数第一次出现的位置,decimal[]: 存储小数位的数组,rem_pos[]: 记录每个余数第一次出现的位置,初始为-1,pos = 0: 当前小数位数,cycle_start = -1: 循环节开始位置

3. 循环直到余数为0或检测到循环:检查当前余数是否出现过,如果出现过,表明小数开始循环,令 cycle_start = remainder_pos[remainder],跳出循环,如果没出现过,remainder_pos[remainder] = pos;计算下一位小数 remainder *= 10,digit = remainder / D,decimal[pos++] = digit,remainder %= D

4. 构造输出字符串:若小数部分无循环,输出 integer + "." + decimal[0..pos-1];若小数部分有循环,输出 integer + "." + decimal[0..cycle_start-1] + "(" + decimal[cycle_start..pos-1] + ")",每76个字符为一行,不足76个字符依旧换行

#include <stdio.h>
#include <string.h>
#define MAX_SIZE 100010
int main(){
    int N, D;
    scanf("%d %d", &N, &D);
    char result[MAX_SIZE];  //存储整个结果字符串
    int pos = 0;  //结果字符串的当前位置
    //处理整数部分
    int integer = N / D;
    pos += sprintf(result, "%d.", integer);
    N = N % D;  //取余数
    if(N == 0){
        result[pos++] = '0';
        result[pos] = '\0';
    }
    else{
        //记录余数出现的位置
        int remainder_pos[MAX_SIZE];
        memset(remainder_pos, -1, sizeof(remainder_pos));
        char decimal[MAX_SIZE];  //存储小数部分
        int decimal_len = 0;  //小数部分的长度
        int cycle_start = -1;  //循环节开始位置
        //长除法计算小数部分
        while (N != 0){
            //检查当前余数是否出现过
            if(remainder_pos[N] != -1){
                cycle_start = remainder_pos[N];
                break;
            }
            //记录余数位置
            remainder_pos[N] = decimal_len;
            //计算下一位小数
            N *= 10;
            int digit = N / D;
            decimal[decimal_len++] = digit + '0';
            N = N % D;
        }
        if (cycle_start == -1){
            //有限小数
            for(int i = 0; i < decimal_len; i++)
                result[pos++] = decimal[i];
        }
        else{
            //循环小数
            //先添加循环节前的部分
            for(int i = 0; i < cycle_start; i++){
                result[pos++] = decimal[i];
            }
            //添加左括号
            result[pos++] = '(';
            //添加循环节
            for(int i = cycle_start; i < decimal_len; i++){
                result[pos++] = decimal[i];
            }
            //添加右括号
            result[pos++] = ')';
        }
        result[pos] = '\0';
    }
    //输出结果,每76个字符换行
    int len = strlen(result);
    for(int i = 0; i < len; i++){
        putchar(result[i]);
        if((i + 1) % 76 == 0 && i != len - 1){
            printf("\n");
        }
    }
    //如果最后一行不足76字符,也要换行
    printf("\n");
    return 0;
}

翻译

In recent years, pre-trained models have played an important role in artificial intelligence research.近些年,在人工智能研究方面,预训练模型扮演了重要的角色

Researchers typically first train a general model using large-scale datasets and then fine-tune it on specific tasks.经典的研究人员首先训练使用大规模的数据集一个通用的模型,然后在特殊任务方面对它进行微调

In this way, the model can utilize the knowledge learned during the pre-training stage to improve the performance of downstream tasks.

通过这种方式,模型可以利用在预训练期间学到的知识,增强下游任务的表现能力

For example, in the field of natural language processing, many language models are pre-trained on massive text corpora例如,在自然语言处理领域,许多的自然语言基于大量的文本被预训练

and achieve excellent results in tasks such as text classification, machine translation, and question answering.

并且取得了优秀的成果,在任务方面,文本分类任务,机器翻译任务和问答任务

The pre-training and fine-tuning framework not only reduces training costs but also improves the generalization ability of models.

预训练和微调框架不仅减少了训练成本,并且增加了模型的泛化能力。

Therefore, this approach has become an important paradigm in modern artificial intelligence research.

因此,这种方式在现代人工智能研究领域是非常重要的典例。

单词

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐