胡凡

[code] PTA 胡凡算法笔记 DAY055

一个人想着一个人 提交于 2020-01-12 06:55:26
文章目录 题目 A1047 Student List for Course 小结 题目 A1047 Student List for Course 题意 输入学生人数和课程数。输入学生名字,选择课程数和各选择课程编号。输出每门课程选课的学生数。课程编号从小到大输出,学生名字按字母序输出。 思路 根据需要输出的内容很明显可以看出这里映射课程号是 key ,学生姓名是 value 。而且因为同一个学生会选择很多课程,所以名字会存在大量的冗余。所以为了减少开销,这里用一个数组建立一个 char* -> int 的哈希表,降低一部分开销。课程的映射表则采用下标和 vector<int> 来表示。 这里哈希算法 getID() 还是跟上一题一样,像计算数转换为 ASCII 进行。输出要求部分课程编号递增直接遍历就好,字母序因为这个哈希算法的特征,直接对应从小到大的顺序排序输出即可。 Code in C++ # include <cstdio> # include <vector> # include <cstring> # include <algorithm> const int M = 26 * 26 * 26 * 10 + 1 ; const int N = 2501 ; // 哈希表 char names [ M ] [ 5 ] ; std :: vector < int >

[code] PTA 胡凡算法笔记 DAY041

梦想与她 提交于 2019-12-18 05:15:48
文章目录 题目 A1049 Counting Ones 小结 题目 A1049 Counting Ones 题意 给出一个数 n ,计算 1~n 过程中所有数字包含 1 的总个数。 思路 这一题暴力会超时,所以需要想想数学规律。最好想到的一个思路就是根据数字的位数去分,因为位数每增加一位不但包含低一位的所有情况还会有个倍数的情况。所以就可以扫描 n 的每一位来进行分类,主要分类就是当前位为 ==0, ==1, > 1 ,因为为 0 的时候这一位的数字 1 就不能计算, >1 的时候左边可以取 0~left 的所有数而不会计算重复。所以假设当前位的数为 cur , a 为10^k次方,左边和右边数分别为 left , right ,则 ① cur == 0 时, ans += left * a (当前位取1时,left只能取到0-left-1,右边000…- a-1 都可以取到) ② cur == 1 时, ans += left * a + right + 1 (除了取0的情况外,还包含单独这位取 1 的情况,即 right+1 ) ③ cur > 1 时, ans += (left + 1) * a (left可以取到 0-left的所有数)) Code in C++ # include <cstdio> int main ( ) { int n ; scanf ( "%d" ,

随机选择算法-来自 胡凡 曾磊的《算法笔记》

折月煮酒 提交于 2019-11-30 07:53:29
#include <cstdio> #include <cstdlib> #include <ctime> #include <algorithm> #include <math.h> using namespace std; const int maxn = 100010; int A[maxn], n; int randPartition(int A[], int left, int right){ int p = (round(1.0*rand()/RAND_MAX*(right - left) + left)); swap(A[p],A[left]); int temp = A[left]; while(left < right){ while(left<right&&A[right]>temp) right--; A[left] = A[right]; while(left<right&&A[left]<=temp) left++; A[right] = A[left]; } A[left] = temp; return left; } //随机选择算法 void randSelect(int A[], int left, int right, int K){ if(left==right) return; int p = randPartition(A,left