写在前面
该博客写了L1中所有的题解,以及每种题对应的算法,真的是 i 了 i 了捏 ^ _ ^
介个是难度分类
- 看了下好像没有结构体 | _ | , 找找之前写过的叭—
正文
L1-003 个位数统计
题
因为输入的数太长,远远大于long long,因此用字符串
char a[1000]="";
scanf("%s",a);
L1-006 连续因子
妙
易错点分析
注意这里求的是连续因子,很多人的想法就是:我把这个数的所有因子都求解出来,然后放进一个数组里,只需要判断是不是连续即可,这样有一个很严重的问题,例如
- 当 N = 1680 时,其因子为
1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 15, 16, 20, 21, 24, 28, 30, 35, 40, 42, 48, 56, 60, 70, 80, 84, 105, 112, 120, 140, 168, 210, 240, 280, 336, 420, 560, 840, 1680
通过这组数据,我们不难发现,貌似连续因子为 2, 3, 4, 5, 6, 7, 8,但实际上我们会发现 2 * 3 * 4 * 5 * 6 * 7 * 8 = 40320 >1680,超过 1680 了。
实际上 1680 = 2 * 3 * 4 * 5 * 7 * 2,它的连续因子仅为 2, 3, 4, 5,所以我们在计算的时候需要考虑所求连续因子的积 num <= N。- 最后,我们要注意判断 N 是不是质数,如果是质数,其只有 1 和 N 两个因子,要注意同时输出(我当时就在这里犯错了)。
正解:
- 对于求一个数的因子,首先从 2 开始遍历,直到 √N 结束。
- 然后我们开始求连续因子,用 num 表示因子之积,count 表示连续因子的个数,从当前的数 i 开始遍历,循环继续的条件为
N % (num * j) == 0,这个不仅仅是判断下一个数是否为因子,更重要的是可以判断 num 是否大于 N,一举两得,有效的避免的易错点 2。
- 最后就是需要判断 N 是否为素数
L1-009 N个数求和(最大公约数)
题
最大公约数的函数!!!
long long int gcd(long long int a,long long int b)
{
return b?gcd(b,a%b):a;
}
L1-011 A-B
- 这里要输入两串字符串(有带空格)->就不能用scanf(“%s”,a)来把一正行字符串读入char a[100]中,因为
scanf()
函数只会读取第一个单词,并在遇到空格、制表符或换行符时停止读取
- 用的是
gets(a)
,从标准输入流(通常是键盘)中读取一行字符串
,并将其存储到指定的字符数组中- 其次:
- 挨个字符比较时,用的是
a[i]==b[j]
,而不是strcmp(a[i],b[j]),这样只会是比较a[i]和b[j]后面的字符串是否相同,而非要的一次只比一个- 还有:
- 字符串进行赋值用的是strcpy,而复制单个字符就直接用
c[n++]=a[i]
即可
L1-016 查验身份证
- 注意是要整形的1,还是字符的 ’ 1 ’
如果下面的是char x[11]={1,0,‘X’,9,8,7,6,5,4,3,2};,那x[0]代表的字符就是阿斯克码为1的字符,根本就不是字符1
- 要往二维字符数组里输入字符串,首先要保证行下标的数要
大于
字符串的长度(因为有'\0'要存
),其次要初始化二维数组为空,初始化的形式很多,如两重循环挨个赋值为‘\0’,或是使用memset函数- 读入字符串可以有两种形式
- 一是scanf(“%s”,b[i]),这种要确保每行的字符串不能有空格和tab
- 二是用gets(b[i]),因为上面有过scanf了,所以要先getchar(),清除缓冲区
数组初始化
int a[50]={
0};
int arr1[2][3] = {
{
5, 2, 4}, {
10, 2, 1} };
int arr1[2][3] = {
0}; /* 所有元素都初始化为0 */
int arr1[2][3] = {
1}; /* 只有arr1[0][0]为1,其他所有元素都初始化为0 */
int arr[10][10];
memset(arr, 0, sizeof(arr3); /* arr中的每个元素都为0 */
char a[50]="";
char a[50][50]={
""};
char arr[10][10];
memset(arr, '\0', sizeof(arr));
取模%
int main() {
int a = 4;
int b = 10;
int c = a % b;
cout << c << endl; // 输出 4 不是2 !!!
return 0;
}
int main() {
int a = 10;
int b = 3;
int c = a % b;
cout << c << endl; // 输出 1
return 0;
}
L1-087 机工士姆斯塔迪奥
题
这里需要开一个100001*100001大小的数组,
如果开在main()里面的话,变量都是定义在栈里面
的,而栈里面的容量一般偏小
,因这个数组太大导致栈溢出了
,所以报了段错误
解决:
1.使用 malloc 函数动态分配内存,例如:
int **a;
a = (int **)malloc((n+1)*sizeof(int *));
for(i=0;i<=n;i++){
a[i] = (int *)malloc((m+1)*sizeof(int));
}
2.把int a[100001][100001]={0};定义在 main 函数外,从而将其定义为全局变量。全局变量存储在静态存储区内存中,而不是栈内存中,因此可以避免栈溢出问题
L1-020 帅到没朋友
题
易错:ID为00035,接收进来的ID为35,输出时要把丢失的三个0补上
printf("%05d",check);
本题好的思想:
- 利用
桶排的想法
- 因为id数为0~99999,int类型的一维数组足以装下,可以将出现的id对应的数组下标里的数给++
- 之后再拿着要查询的数遍历数组,看看有没有为0的(为0表示没朋友,上面++是指对有朋友的进行++)
- 这样就不用说定义二维数组去乱搞了~
通讯录排序(结构体排序)
交换结构体数组中的两个结构体的所有元素:
- 可以
将结构体变量直接进行赋值
,而不用p[1].a=p[2].a这样每个元素分别赋值
struct MyStruct {
int x;
double y;
char z;
};
struct MyStruct p[3];
接下来,要交换p[1]和p[2]里面的全部元素
struct MyStruct temp; //定义临时变量t
temp = p[1];
p[1] = p[2];
p[2] = temp;