5, 5, 4, 5, 6, 3, 7, 6 }; /* 6 = 3+3 -> 7*2 = 14 7 = 3+4 -> 7+4 = 11 5 = 3+2 -> 7+1 = 8 4 = 4 -> 4 3 = 3 -> 7 2 = 2 -> 1 */ void solve() { cin >> n; map<int, int> mp; mp[6] = 14, mp[7] = 11 LL n) { while(n % 2 == 0) n /= 2; return n == 1; } void solve() { LL n; cin >> n; = son[u]) dfs2(v, u, line+1); } if(son[u]) dfs2(son[u], u, line); } void 1) << '\n'; // -(sum+1)/2 } else { cout << sum/2 << '\n';
算法竞赛的目的是找到解决问题的答案,不是比谁的答案更高级!!! r,高为h 则该圆柱体的表面积的表达为 PI * r * 2 + 2 PI * r 问题描述:输入底面半径r,和高度h,输出圆柱的表面积,保留三位小数 样例: 3.5 9 Area = 274.889 r,&h); s1 = pi*r*r; s2 = 2*pi*r*h; s = s1*2+s2; printf("Area = %.3f",s); return 0; } 这里要注明几点 - b; 方法三 a=a^b; b=a^b; a=a^b; 方法四 int t; t = a; a = b; b = t; */ 这个交换数据的题目还有两种,一种使用指针,还有是用函数,在算法竞赛中 #include int main() { int a,b,n,m; scanf("%d%d",&n,&m); a = (4*n-m)/2; b = n - a; if(m%2 == 1||a
1100+b*11); } return 0; } 二、7744问题 问题描述:输入一个整数,判断其是否为完全平方数(用一个int 形变量m存储sqrt(n)四舍五入后的整数,然后判断m^2是否等于 三、3n + 1 问题 问题描述:对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半,经过若干次这样的变换,一定会使n变为1,例如3—>10—>5—>16—>8—>4—>2— = 1) { if(n%2 == 1) n=3*n +1; else n=n/2; count++; } printf("%d",count); return 0; } 0.785399 源代码: #include int main() { double sum =0; for(int i = 0;;i++) { double term = 1.0/(i*2+ +2!+3!+4! * * * n!的末六位(不含前导0,只保留后六位数字)。
而区间得到的结果,最多是2*n-1,联系数据范围,对答案有贡献(减少)的数较少。 所以,利用异或运算的可逆性,从对答案有贡献的值倒推。 其实也就是s[p-1]出现的次数, p为让[p, i] 的区间异或和符合题目的区间起点) void solve() { LL n; cin >> n; vector<int> cnt(2* i = 0; i < n; i ++) { int x; cin >> x; s ^= x; for(LL j = 0; j*j < 2* \geq 2),所以,令a[x]为gcd=x的组合的数量, a[x] = {n/k \choose 2} - a[tk] \space\space\space (t \in Z \bigcap \space in one group a[i] = (n/i)*(n/i-1)/2; for(LL j = i*2; j < n; j += i) a[i]
因为一次滑行就要一格能量,所以,一次尽量长,所以直接一条通到底是最好的(如题中样例解释图例) 之后便可以尝试,发现除了(1,1)需要特判,其他结果都是 (m - 1) * 2 + n B 因为是下取整, C 发现如果所有数都一样,题目中所定义的值为n*(n+1)/2 那后面就是修改的事情了(因为一开始的数据也可以看作是修改来的) 我们可以发现,只有当修改的数据对整体的所定义值的影响,只和 与旁边的数的关系和 CODE D #pragma GCC optimize(2) #include <bits/stdc++.h> #define all(x) (x).begin(), (x).end() using
用cnt来记,是Q就cnt ++, 是A就cnt = max(cnt-1, 0) B 其实我乱搞构造的,证明的话可以看cf官方题解,大概就是先反证法证明答案不大于[n/2],再证明[n/2]可构。 n/2, n, n/2-1, n-1, ... 分奇偶稍微讨论下即可 for (int i = 0, t = n / 2 + n % 2; i < n; i += 2, t--) a[i] = t; for (int i = 1, t = n; i == 0 && a[i] == last || cnt0 % 2 && a[i] ! * (n - 1) / 2 % P, ans = 0; for (LL i = cnt; i >= 1; i--) ans = (ans + tot * qpm(i * i, P - 2) % P) %
机器学习算法竞赛实战-竞赛问题建模 更新《机器学习算法竞赛实战》一书的阅读笔记,更多详细的内容请阅读原书。 准确方法 解决数据集过大或者正负样本不均衡的方法: 简单随机抽样:有放回和无放回 分层采样:评分加权处理(对不同的类别进行加权)、欠采样(随机欠采样、Tomek Links)、过采样(随机过采样、SMOTE算法 如果评价指标是AUC:处理或不处理差别不大 如果正负样本同等重要,无需多做处理 线下评估策略 强时序性问题:将数据按照时间的先后顺序进行排序,选择最近时间的数据作为测试集 弱时序性问题:K折交叉验证 K=2, 2折交叉验证:将数据分为训练集和测试集,受数据划分方式影响大 K=N,N折交叉验证(留一验证 leave-one-out Validation),N-1个训练集,1个测试集;训练过程计算量大 K=5或者 # 独热码 import lightgbm as lgb # lgb模型 import warnings warnings.filterwarnings("ignore") 加载数据 In [2]
SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE)。 (百度百科) 这也是为什么在算法竞赛中我们很少使用bellman-ford算法的原因 SPFA 一般:O(m) 线性 最坏:O(nm) int n; // 总点数 int h[N], w[N]
friend bool operator<(const Node &a, const Node &b) { return a.s < b.s; } } st[2] ; int dxy[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0}, }; map<int, int> d[2]; // 未用到 bool read_data() { for (int i = 0; i < 2; i++) for (int j = 0; j < 4; j++) cin return false; ; } // 队列q扩展一次 int expand(queue<Node> &q, map<int, int> &mp1, map<int, int> &mp2) (nt.s)) return mp1[nt.s] + mp2[nt.s]; // cout << mp1[nt.s] + mp2
邻接表,h[]忘记初始化。多组数据时,idx未初始化(会造成数组越界) 当使用并查集时,注意自己写的并查集是不是fa[x]随时都是x的祖宗,若不是,记得要用GetFa(x) 变量名有冲突y1, next, prev, has ... 在特别情况下.size()和int整型变量比较时会出错,所以尽量保证式子的运算结果是正数,因为如果是负数,unsigned int类型的变量会变成超大的正数。 priority_queue 默认是大根堆 < Type,vector,greater >是小根堆 图论采用虚拟源点时
克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同,它的时间复杂度为O(eloge)(e为网中的边数),所以,适合于求边稀疏的网的最小生成树 。
一、引言: 模拟算法,简单来说,就是按照题目描述的步骤或规则,一步一步地用代码实现解决问题的过程。就像是你在玩一个游戏,游戏有它自己的规则,而你需要根据这些规则来做出相应的动作以完成特定的目标。 笔者提醒: 模拟这个算法其实非常难,主要是逻辑上的麻烦,但正常刷题时我们都不把模拟的逻辑思维理清就直接做,如果这题没有太水的话,是非常容易错的。 模拟可以与任何算法同时出现,比如模拟与动归dp、模拟与搜索之类的。 而接下来的入门题型,就是“水题”!基础与进阶代码量会大一些。 但这没啥好担心的,这毕竟是算法能力提升的基石-敲代码能力( ̄︶ ̄)↗ 。 三、练习: 模拟类型、是以编程题考察。 模拟算法 (算法详解+例题) 3、C++算法:模拟 ( •̀ ω •́ )✧点击这里,继续学习其他模块吧!
常量n }; 但在算法竞赛中的 “枚举”,可不止这么简单。重点:算法中的枚举,是一种思想,而不是一种语法结构! ( •̀ ω •́ )y 二、枚举算法基础 核心思想:将所有可能罗列出来,逐一检验每个解,是否符合条件。 for(int x2 =0;x2<20;x2++) { for (int y2= 0; y2 <21; y2++) { }else { double k =(y2-y1)*1.0 /(x2-x1); double b = (y1*x2 - y2*x1)*1.0/(x2-x1 样例 22:考虑字符串 X=1011X=1011,其中 X2=X1⊕S1=1⊕1,X3=X2⊕S2=0⊕1,X4=X3⊕S3=1⊕0X2=X1⊕S1=1⊕1,X3=X2⊕S2=0⊕
Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。 该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。 (百度百科) Floyd算法用于求多源汇最短路问题,通俗来讲就是求图中任意两点间的最短距离 时间复杂度: O(n^3) 初始化: for (int i = 1; i <= n; i ++ ) (int j = 1; j <= n; j ++ ) if (i == j) d[i][j] = 0; else d[i][j] = INF; // 算法结束后
匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法,并推动了后来的原始对偶方法。 (百度百科) 匈牙利算法用于求二分图的最大匹配问题 时间复杂度:O(mn),实际运行时间一般小于O(mn) int n1, n2; // n1表示第一个集合中的点数,n2表示第二个集合中的点数 int h[N], e[M], ne[M], idx; // 邻接表存储所有边,匈牙利算法中只会用到从第一个集合指向第二个集合的边,所以这里只用存一个方向的边 int match[N];
向上的箭头代表提高阶段需掌握的算法。 奖杯代表NOI级 Q.E.D.
A 不难发现结果必然 <=2 我int*int过程爆了int(( LL读入通分即可。 只需要扫一遍即可 赛时题目结束(( ---- D 发现关系之和相邻的前后有关,同时bi是单调递增,采用dp 直接可以想到暴力的O(n2)dp。 (呜,我没想到(( D1 相比D2,ai的大小只有200,发现如果bi>=(1<<8)就必须满足bi-1>=bi>>8<<8(八位以上要相同,因为八位以上此时只与bi有关。
2个,一次最多能涂两个相同颜色的,所以答案显然为1。 3个,此时有一种字母有两个,分为两个相邻与两个相隔的情况,可以发现都只需要一步可以变为有三个相邻的状态,答案为2。 如果,边缘的走法可以过,那最小步数就为 n+m-2,否则若两边都不能过,容易想象出这是终点与起点被隔断的情况,即无解,也没有必要去分析其他的走法。 询问的内容为,把t接在s后面,那么对于接在里面的t的每一位来说,把它作为后缀的字符串,出现在前面的离它最近的地方在哪里,即kmp算法中next[i]。 CODE A #pragma GCC optimize(2) #include <bits/stdc++.h> #define all(x) (x).begin(), (x).end() using memset(vis, 0, sizeof vis); int cnt = 0; char ch[3]; cin >> ch; for (int i = 0; i < 2;
int g[N][N]; // 存储每条边 int dist[N]; // 存储1号点到每个点的最短距离 bool st[N]; // 存储每个点的最短路是否已经确定 // 求1号点到n号点的最短路,如果不存在则返回-1 int dijkstra() { memset(dist, 0x3f, sizeof dist); dist[1] = 0; for (int i = 0; i < n - 1; i ++ ) { int t = -1;
{ while (j < i && check(i, j)) j ++ ; // 具体问题的逻辑 } 常见问题分类: (1) 对于一个序列,用两个指针维护一段区间 (2)