《冬训周报二》
埃氏筛选法
概念
埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
步骤
-
列出2以后的所有序列:
-
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
-
标出序列中的第一个素数,也就是2,序列变成:
-
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
-
将剩下序列中,划掉2的倍数,序列变成:
-
2 3 5 7 9 11 13 15 17 19 21 23 25
-
如果这个序列中最大数小于最后一个标出的素数的平方,那么剩下的序列中所有的数都是素数,否则回到第二步。
-
本例中,因为25大于2的平方,我们返回第二步:
-
剩下的序列中第一个素数是3,将主序列中3的倍数划掉,主序列变成:
-
2 3 5 7 11 13 17 19 23 25
-
我们得到的素数有:2,3
-
25仍然大于3的平方,所以我们还要返回第二步:
-
序列中第一个素数是5,同样将序列中5的倍数划掉,主序列成了:
-
2 3 5 7 11 13 17 19 23
-
我们得到的素数有:2,3,5 。
-
因为23小于5的平方,跳出循环.
C++代码实现
#include <stdio.h> #include <math.h> bool is_prime[1000]; int main(){ int n; scanf("%d", &n); for(int i = 0; i <= n; i++){ is_prime[i] = true; //初始化所有的数为素数 } for(int i = 2; i <= sqrt(n); i++){ //从第一个素数2开始筛选 if(is_prime[i]){ //如果是素数 for(int j = i*i; j <= n; j += i){ //则剔除掉它的倍数 is_prime[j] = false; } } } for(int i = 2; i <= n; i++){ if(is_prime[i]){ printf("%d\n", i); } } return 0; }
记录一道平面几何题
题目:
题解:
需要画几张图来观察规律,在这里就直接引用一下大佬画的图(绝对不是因为我画的烂)
可以发现三点:1,重边增加区域数。2,每增加一条边(除开重边)区域数+1。3,新边如果和之前的边每有一个交点则区域数+1。
代码实现:
#include<bits/stdc++.h> using namespace std; double s[1010][2]; long long ans; bool st[1010]; pair<long double, long double> p; int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> s[i][0] >> s[i][1]; set<pair< double, double> > points; for (int j = 0; j < i; j++) { if (st[j])continue; if (s[i][0] == s[j][0]) { if (s[i][1] == s[j][1]) { st[i] = true; break; } else continue; } p.first = (s[j][1] - s[i][1]) / (s[i][0] - s[j][0]); p.second = s[i][0] * p.first + s[i][1]; points.insert(p); } if (!st[i])ans += points.size() + 1; } cout << ans + 1; }
C++中pair的用法以及函数的多个返回值的用法
pair类型:
pair 是 一种模版类型。每个pair 可以存储两个值。这两种值无限制。也可以将自己写的struct的对象放进去
pair<string,int> p;
pair<int ,int > p;
pair<double,int> p;
应用:
如果一个函数有两个返回值 的话,如果是相同类型,就可以用数组返回,如果是不同类型,就可以自己写个struct ,但为了方便就可以使用 c++ 自带的pair ,返回一个pair,其中带有两个值。除了返回值的应用,在一个对象有多个属性的时候 ,一般自己写一个struct ,如果就是两个属性的话,就可以用pair 进行操作
应用pair 可以省的自己写一个struct,如果有三个属性的话,其实也是可以用的pair 的 ,极端的写法 pair <int ,pair<int ,int > >(后边的两个 > > 要有空格,否则就会是 >> 位移运算符)
makr_pair:
pair<int ,int >p (5,6);
pair<int ,int > p1= make_pair(5,6);
pair<string,double> p2 ("aa",5.0);
pair <string ,double> p3 = make_pair("aa",5.0);
有这两种写法来生成一个pair。
每个pair 都有两个属性值 first 和second
cout<<p1.first<<p1.second;
注意是属性值而不是方法。
由于pair类型的使用比较繁琐,因为如果要定义多个形同的pair类型的时候,可以时候typedef简化声明:
typedef pair<string, string> author;
author pro("May", "Lily");
author joye("James", "Joyce");
树状数组
树状数组算是我以前学过的后来又忘了的一个算法吧orz
自己写的话总感觉不太详细,这里就放上我看过的一篇详解来理解