组合数素数判定++和* *t=*afor循环你真的门儿清吗救济金发放

news/2024/10/20 23:02:47/

目录

P63_习题4-1_组合数

为什么m = n-m

P64_习题4-3_素数判定

为什么要floor

到底为什么判断到sqrt(n)即可

++和*

 *t=*a

for循环你真的门儿清吗

为什么要把较大的数组放在main函数外

P82_eg4-3_救济金发放_UVa133


P63_习题4-1_组合数

 防止溢出,又因为m <= n,所以用n!/m!=(m+1) (m+2)…(n-1)n

long long C(int n, int m) {if(m < n-m) m = n-m;long long ans = 1;for(int i = m+1; i <= n; i++) ans *= i;for(int i = 1; i <= n-m; i++) ans /= i;return ans;
}

为什么m = n-m

然后还要知道到底为什么要把n!/m!给约分。因为我们这里,n肯定是最大的数,要防止n!的溢出。约分之后这个值就变成了从m+1到n的累乘。

而我们知道 

这是一件好事。着说明我们可以把m的值变成我们想要的。

我们需要从m+1到n的累乘,那一定是m越大计算的次数就越小。

那么,这个小和大怎么来分辨呢。就是用if(m < n-m)。

P64_习题4-3_素数判定

素数判定。编写函数,参数是一个正整数n,如果它是素数,返回1,否则返回0。

int isPrime(int n){if(n == 1) return 0;for(int i = 2;i <= sqrt(n);i++){if(n % i == 0) return 0;}return 1;
}
int is_prime(int n)
{if(n == 1) return 0;int m = floor(sqrt(n) + 0.5);for(int i = 2; i <= m; i++)if(n % i == 0) return 0;return 1;
}

为什么要floor

 

到底为什么判断到sqrt(n)即可

仔细思考就会发现,其实数字x的因数分成两大部分,一部分是小于x的平方根,另外一部分大于x的平方根,小于平方根和大于平方根的部分是一一对应的,因而可以只判断从2到平方根的数字是否都能被整除即可。

++和*

 *t=*a

void swap(int* a, int* b)
{int *t;*t = *a; *a = *b; *b = *t;
}

这个程序错在哪里?t是一个指向int型的指针,因此*t是一个整数。用一个整数作为辅助 变量去交换两个整数有何不妥?事实上,如果用这个函数去替换程序4-6,很可能会得到“4 3”的正确结果。为什么笔者要坚持说它是错误的呢? 问题在于,t存储的地址是什么?也就是说t指向哪里?因为t是一个变量(指针也是一个 变量,只不过类型是“指针”),所以根据规则,它在赋值之前是不确定的。如果这个“不确 定的值”所代表的内存单元恰好是能写入的,那么这段程序将正常工作;但如果它是只读 的,程序可能会崩溃。读者可尝试赋初值int *t = 0,看看内存地址“0”能不能写。

for循环你真的门儿清吗

for循环中的最后一个语句是最后执行的,也就是说无论写成先自加还是后自加都是一个效果

为什么要把较大的数组放在main函数外

局部变量也是放在堆栈段的。栈溢出不一定是递归调用太多,也可能是 局部变量太大。只要总大小超过了允许的范围,就会产生栈溢出。

P82_eg4-3_救济金发放_UVa133

n(n<20)个人站成一圈,逆时针编号为1~n。有两个官员,A从1开始逆时针数,B从n开
  始顺时针数。在每一轮中,官员A数k个就停下来,官员B数m个就停下来(注意有可能两个
  官员停在同一个人上)。接下来被官员选中的人(1个或者2个)离开队伍。输入n,k,m
  输出每轮里被选中的人的编号(如果有两个人,先输出被A选中的)。例
  如,n=10,k=4,m=3,输出为4 8, 9 5, 3 1, 2 6, 10, 7。注意:输出的每个数应当恰好占3列。
  【分析】
  仍然采用自顶向下的方法编写程序。用一个数组表示人站成的圈。为了避免
  人走之后移动数组元素,用0表示离开队伍的人,数数时跳过即可。
  
  注意go这个函数。
  当然也可以写两个函数:逆时针go和顺时针go,但是仔细思考后发现这两个函数可以合并:
  逆时针和顺时针数数的唯一区别只是下标是加1还是减1。把这个+1/-
  1抽象为“步长”参数,就可以把两个go统一了

#include<stdio.h>
#define maxn 25
int n, k, m, a[maxn];
//逆时针走t步,步长是d(-1表示顺时针走),返回新位置int go(int p, int d, int t) {while(t--) {do { p = (p+d + n-1) % n + 1; } while(a[p] == 0); //走到下一个非0数字}return p;
}int main() {while(scanf("%d%d%d", &n, &k, &m) == 3 && n) {for(int i = 1; i <= n; i++) a[i] = i;int left = n; //还剩下的人数int p1 = n, p2 = 1;//p1为A,-1是顺时针while(left) {p1 = go(p1, 1, k);p2 = go(p2, -1, m);printf("%3d", p1); left--;if(p2 != p1) { printf("%3d", p2); left--; }a[p1] = a[p2] = 0;if(left) printf(",");}printf("\n");} return 0;
}

注意go这个函数。当然也可以写两个函数:逆时针go和顺时针go,但是仔细思考后发现这两个函数可以合并:逆时针和顺时针数数的唯一区别只是下标是加1还是减1。把这个+1/- 1抽象为“步长”参数,就可以把两个go统一了。

int go(int p, int d, int t) {while(t--) {do { p = (p+d + n-1) % n + 1; } while(a[p] == 0); //走到下一个非0数字}return p;
}

感觉本题最难的地方就是这个go函数。作者的抽象能力确实很强,能把两件事(逆时针和顺时针)抽象出一个模型然后统一写在一个函数中。


http://www.ppmy.cn/news/10285.html

相关文章

leetcode 1658. 将 x 减到 0 的最小操作数

给你一个整数数组 nums 和一个整数 x 。每一次操作时&#xff0c;你应当移除数组 nums 最左边或最右边的元素&#xff0c;然后从 x 中减去该元素的值。请注意&#xff0c;需要 修改 数组以供接下来的操作使用。 如果可以将 x 恰好 减到 0 &#xff0c;返回 最小操作数 &#x…

字节跳动青训营笔试题解

文章目录前言一、单选题二、多选题三、编程题T1.旋转数组最大值题目思路代码T2.社交圈题目思路代码四、简答题题目思路前言 第五届字节跳动青训营-后端专场笔试题解&#xff0c;简单做了一下&#xff0c;选择题和简答题不知道是否正确&#xff0c;编程题是通过了的&#xff0c…

【vue2】计算属性(computed)与侦听器(watch)详解

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;计算属性与侦听属性的用法 目录&#xff08;文末有给大家准备好的Xmind思维导图&#xf…

【深度学习】李宏毅2021/2022春深度学习课程笔记 - Adversarial Attack(恶意攻击)

文章目录一、基本概念1.1 动机1.2 恶意攻击的例子1.3 如何攻击&#xff1f;二、White Box vs Black Box三、One Pixel Attack四、Universal Adversarial Attack五、Beyond Image六、Attack in the Physical World七、Adversarial Reprogramming八、Backdoor in Model九、防御9.…

数据结构与算法【树】

二叉树性质 满二叉树 深度为k&#xff0c;有2k−12^{k}-12k−1个结点的二叉树&#xff0c;为满二叉树。 完全二叉树 完全二叉树的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面…

逻辑漏洞渗透与攻防(六)之其他类型逻辑漏洞

目录 其他类型逻辑漏洞 数据包重放漏洞 条件竞争漏洞 订单金额任意修改 接口无限制枚举 支付漏洞 修改商品数量 修改支付状态 修改附属值 越权支付 无限制试用 支付漏洞总结 SRC中的逻辑漏洞总结 其他类型逻辑漏洞 数据包重放漏洞 漏洞介绍&#xff1a;通…

揣着一口袋的阳光满载而归--爱摸鱼的美工(13)

-----------作者&#xff1a;天涯小Y 揣着一口袋的阳光满载而归&#xff01; 慷懒周末 睡到自然醒&#xff0c;阳光洒在书桌上 套进宽松自在的衣服里 出门&#xff0c;去楼下坐坐 在阳光里吃午餐 在阳光里打个盹 在阳光里看猫咪上蹿下跳 在阳光里点个咖啡外卖 虚度时光&#xf…

【Acwing 周赛#85】AcWing 4792. 最大价值 + AcWing 4793. 危险程度

目录 4791. 死或生 - 简单模拟ac 4792. 最大价值 - 简单构造ac 4793. 危险程度 - dfs / 并查集 1、dfs 2、并查集 4791. 死或生 - 简单模拟ac import java.util.*;class Main {public static void main(String[] args){Scanner scnew Scanner(System.in);int nsc.nextInt(…