[蓝桥杯]校内培训交流会总结

网友投稿 1279 2022-09-06

[蓝桥杯]校内培训交流会总结

[蓝桥杯]校内培训交流会总结

//【蓝桥杯培训交流会 整理]//破解编程题目/* 破解编程题目 编程题是如何评测的? 黑箱测试: 程序-> 编译->运行->比对 运行: 1. 将stdin重定向data.in 2. 将stdout重定向到user.out 比对: 比对data.out和user.out是否相同 出题人如何准备数据? 出题人会预先设定一组数据: data0.in - data0.out data1.in - data1.out data2.in - data2.out 出题人目的: 测试程序正确性和效率 随机数据 边界数据 特殊数据(某些算法会退化) 规模最大的数据 较小规模数据(给部分分) 我们如何应对? 根据数据规模和时间限制估计复杂度 (现在主流电脑1秒 = 10^8复杂度量级) 放弃满分,争取部分分 一些常见的数据规模和出题人期望的复杂度 N <= 12 O(N!) N <= 20 O(2N) N <= 100 O(N3) N <= 1000 ~ 10000 O(N2) N <= 100000 ~ 1000000 O(NlogN) N <= 1000000+ O(N) 有些题目会说明有部分分的数据范围 有些题目没有说明,需要自行判断 自测:对拍 1. sample只是用来举例说明格式和题意, 实际系统测试使用的数据比sample复杂得多。 2. 把自己当出题人,字母测出来选手程序的BUG低效 3. 出题人的目的:测试程序正确性和效率 用程序生成随机数据生成 举例:随机生成N个0~M的整数 用程序生成特殊大数据 [例] #include #include using namespace std ; int n,m,seed ; int main() { cin >> n >> m >> seed ; srand(seed) for(int i = 0; i < n; i++) { int x = rand() % m ; cout << x << endl ; } return 0 ; } “对拍” 很多时候一道题目都有很简单的朴素算法,但是效率很低 我们要拿满分不得不实现一个更复杂的高效算法 为了避免程序有BUG,我们可以再写一个朴素算法”对拍” 举例:朴素匹配 VS KMP 朴素算法很容易实现: if (s.find(p)) … 写一个脚本/程序,不断执行以下步骤 生成一个随机小数据 运行朴素匹配程序,得到结果文件1 运行KMP程序,得到结果文件2 比较文件1和文件2 大数据朴素程序太慢,小数据也能测正确性 对拍过程中,我们可以做别的题目 需要一些Windows命令行和脚本的知识 【大赛题型】 结果填空题: 1.已知测试数据,实现超长(~4小时)的编程大题。 2.难度相对简单,告诉你怎么做 3.程序已经有大致框架,可以测试 4.“送分题”,丢分很可惜 5.但是也有相当一部分没有满分 程序填空题 从main函数开始,自顶向下 1.理解变量的作用 2.推测每一条语句在做什么 3.特别是每一个循环在做什么 4.如果有递归,推测一个函数整体在做什么 5.如果所填内容不影响程序流程, 不妨先随便填一个然后运行程序,了解流程 如何答好程序填空题 1.多读别人的程序 2.出题人的程序相对比较精炼 3.同样的逻辑,不同人可能有不同的写法 4.见多识广,精益求精 5.蓝桥杯历届题目在网上都能搜到别人公开的程序 6.NOIP中有很多完善程序的题目,他山之石 编程大题 基础难度: 基础:枚举、搜索、模拟 考察基本功、基本的代码能力 学习编程的第一道门槛: “我不会高大上的算法和数据结构,程序可能超时,但是不会出错” 编程基础最重要 蓝桥杯中数列最多的题目类别 【枚举】枚举的要点:如果我一个算法根据数据范围、时限我知道要超时,我们怎么减少复杂度?方法不外乎就是1减少枚举的变量,原来我要枚举4个变量,能不能只枚举3个? 2就是缩小枚举范围,我能不能通过改变枚举的变量,减少范围? 确定需要的枚举变量 确定枚举的范围(不重不漏)1是二分,二分查找、二分搜索非常有效,一般是复杂度从O(N)降到O(logN),使用范围也很广。2是用Hash,空间换时间。3此外还有一些常用的套路:比如双指针,Leetcode上对应的分类是two pointer,直译过来就是双指针,大概的思想就是滑动窗口。4还比如前缀后缀和,也是空间换时间的思路。【常见的枚举题类型】: 枚举答案: 答案难以计算,易于验证 按某个顺序(从小到大)枚举每个可能的答案,验证。 例题:哪天返回、猴子分香蕉、以及一些逻辑推理题 枚举日期: 例题:某年某月某日星期几 关键:判断某个日期是不是合法 int days[-1,31,28,31,30,31,30,31,31,30,31,30,31] ; is_leap_year(int year) 枚举数位:(枚举有规律的数列) 例题:等腰三角形 12345678910111213…. 第N个数位是几 1,2,2,3,3,3,4,4,4,4,…… 关键: 分离各位数字,设计状态变量 枚举位置、方向 例题:字母阵列、回形填数 关键: int dx = {-1, 1, 0, 0}; int dy = {0, 0, -1, 1} 方向数组描述上下左右,设计状态变量 基础的枚举类型: 选择枚举变量:优化思想 例题:第几个幸运数 二分、哈希、双指针、前缀、后缀和STL-set用法:set跟vector差不多,它跟vector的唯一区别就是,set里面的元素是有序的且唯一的,只要你往set里添加元素,它就会自动排序,而且,如果你添加的元素set里面本来就存在,那么这次添加操作就不执行。/*———————————————————————————————————————————————————————————题目:平方十位数问题描述: 由0~9这10个数字不重复、不遗漏,可以组成很多10位数字。这其中也有很多恰好是平方数(是某个数的平方)。比如:1026753849,就是其中最小的一个平方数。请你找出其中最大的一个平方数是多少?  ————————————————————————————————————————————————————————————*//*思路1:枚举答案X [9876543210, 1026753849]判断是不是恰好0-9十个数字判断是不是完全平方数令Y = int(sqrt(X))判断Y * Y == X?*/ /*思路2:枚举Y [100000, 30000]计算X = Y * Y判断X是不是恰好0-9十个数字 *///常见问题:分离整数X的个位数字if(X == 0) { //特判}while(X) { int d = X % 10; //处理d X /= 10;}bool valid(int x) { //恰好包含0-9 if(x == 0) return false; set s; while(x) { int d = x % 10; s.insert(d); x /= 10; } return s.size() == 10;}/*————————————————————————————————————————————————————————————*/#include #include using namespace std;//判断是不是包含0~9的代码bool contains0_9(long long x){ if(x==0)return false;//这里没什么用,算法的严谨性 set s; //分离x的各位数字,每次把x的末尾数字分离出去 while(x) { int d=x%10;//d是x末位数字 s.insert(d);//把d插入s中 x/=10;//更新x } return s.size()==10;}int main(int argc, char *argv[]) { //c语言中基本整型int占据两个字节, //取值范围-2^15--2^15-1(-32768--32767)肯定不够 //用 long long for (long long i=100000; i--; i>30000) {//找最大,倒着来 long long x=i*i; if(contains0_9(x)) { cout << x << endl; return 0; } } return 0;}//输出:结果为:9814072356。 /*———————————————————————————————————————————————————————————题目:四平方和问题描述:四平方和定理,又称为拉格朗日定理:每个正整数都可以表示为至多4个正整数的平方和。如果把0包括进去,就正好可以表示为4个数的平方和。比如:5 = 0^2 + 0^2 + 1^2 + 2^27 = 1^2 + 1^2 + 1^2 + 2^2(^符号表示乘方的意思)对于一个给定的正整数,可能存在多种平方和的表示法。要求你对4个数排序:0 <= a <= b <= c <= d并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法程序输入为一个正整数N (N<5000000) //思路1:枚举abcd,判断a^2+b^2+c^2+d^2是否等于N分析规模:a:0 ~ sqrt(5000000 / 4)b:0 ~ sqrt(5000000 / 3)c:0 ~ sqrt(5000000 / 2)d : 0 ~ sqrt(5000000)abcd枚举的范围大约都是1000~2000总枚举量 10^12 还记得我们的经验吗? 1秒 = 10^8 优化套路一:减少枚举变量,以计算代枚举思路2:枚举abc,判断N-a^2-b^2-c^2是不是完全平方数分析规模:a:0 ~ sqrt(5000000 / 4)b:0 ~ sqrt(5000000 / 3)c:0 ~ sqrt(5000000 / 2)总枚举量 10^9 还是会超时!问题:能不能只枚举ab?分析:只枚举ab,那么余下R=N-a^2-b^2能否快速求出c^2+d^2=R的解?(或者快速判断出无解)例如:N = 5, 当前枚举a=b=0。c^2+d^2 = 5,能不能快速求出解c=1, d=2。优化套路二:用哈希预处理出的可行解思路2:先预处理出c^2+d^2=R的可行解,保存在哈希表里。枚举ab,通过查表判断无解或者有解。————————————————————————————————————————————————————————————*//*空间换时间的利器:哈希查找一个东西存不存在是我们经常遇到的一个基本问题哈希(hash):把将来需要查找的值预先保存起来,减少查找时间。基本问题:给一个数组[1, 3, 13, 4, 5, 27 … ]询问某个值V是否在数组里(在数组哪个位置)遍历数组、枚举:O(N)哈希:O(N)预处理,O(1)查询实现方法:数组(int my_hash[值域])、set(TreeSet)、map(TreeMap)、unordered_set(HashSet)、unordered_map(HashMap)unordered_set可以把它想象成一个集合,它提供了几个函数让我们可以增删查:unordered_set::insertunordered_set::findunordered_set::erase由于它内部是用哈希表实现的,所以上面这三个函数的平均时间复杂度都是O(1)。我们可以看一个简单的例子。#include#includeusing namespace std ;int main(){ unordered_set myset ; myset.insert(3) ; myset.insert(5) ; myset.insert(3) ; cout << myset.size() << endl ; myset.erase(3) ; if(myset.find(3) == myset.end()) cout << "3 not found" endl ; return 0 ;}#include头文件。然后有两点需要注意:一是这个容器是个集合,所以重复插入相同的值是没有效果的。二是find的返回值是一个迭代器(iterator),如果找到了会返回指向目标元素的迭代器,没找到会返回end() *///#includeint n;unordered_map f;int main(){ cin >> n; for(int c = 0; c * c <= n / 2; c++) { for(int d = c; c * c + d * d <= n; d++) { if(f.find(c * c + d * d) == f.end()) { f[c * c + d * d] = c; } } } for(int a = 0; a * a * 4 <= n; a++) { for(int b = a; a * a + b * b <= n / 2; b++) { if(f.find(n - a * a - b * b) != f.end()) { int c = f[n - a * a - b * b]; int d = int(sqrt(n - a * a - b * b - c * c) + 1e-3); cout << a << ' ' << b << ' ' << c << ' ' << d << endl; return 0; } } } return 0;}//思路2int n;unordered_map f;int main(){ cin >> n; for(int c = 0; c * c <= n / 2; c++) { for(int d = c; c * c + d * d <= n; d++) { if(f.find(c * c + d * d) == f.end()) { f[c * c + d * d] = c; } } } for(int a = 0; a * a * 4 <= n; a++) { for(int b = a; a * a + b * b <= n / 2; b++) { if(f.find(n - a * a - b * b) != f.end()) { int c = f[n - a * a - b * b]; int d = int(sqrt(n - a * a - b * b - c * c) + 1e-3); cout << a << ' ' << b << ' ' << c << ' ' << d << endl; return 0; } } } return 0;}/*———————————————————————————————————————————————————————————题目:2018年倍数问题问题描述: 众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。数据规模与约定 对于 30% 的数据,n <= 100。对于 60% 的数据,n <= 1000。对于另外 20% 的数据,K <= 10。对于 100% 的数据,1 <= n <= 10^5, 1 <= K <= 10^3,给定的 n 个数均不超过 10^8。————————————————————————————————————————————————————————————*///思路://在n个数中找出3个数的和是k的倍数并且要最大,三重循环肯定是不可取的,所以用dfs。#include#include#include#include#include#include#include#include#include#include#includeusing namespace std; int n, k, ans = 0;int temp[3], num[100005], vis[100005] = { 0 }; void dfs(int s){ if (s == 3) { int t = temp[0] + temp[1] + temp[2]; if (t%k == 0 && t > ans) ans = t; return; } else { for (int i = 0; i < n; i++) { if (!vis[i]) { temp[s] = num[i]; vis[i] = 1; dfs(s + 1); vis[i] = 0; } } }} int main(){ scanf("%d%d", &n, &k); for (int i = 0; i < n; i++) scanf("%d", &num[i]); dfs(0); printf("%d\n", ans); return 0;}/*———————————————————————————————————————————————————————————题目:分巧克力问题描述: 儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:1. 形状是正方形,边长是整数 2. 大小相同 例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?输入:第一行包含两个整数N和K。(1 <= N, K <= 100000) 以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)  ————————————————————————————————————————————————————————————*///#include#define N 100000bool ok(int m);int a,b;int H[N],W[N];int main(){ int c,l=1,max=0,r,ans=1; long long m; scanf("%d %d",&a,&b); for(c=0;c=b) return true; return false;}/* 求部分和的利器:前缀和对于一个数组A = [A1, A2, … AN],我们将从Ai到Aj的和称作部分和,记为S[i, j]。计算部分和是非常常见的问题为了减少计算部分和的时间复杂度,我们往往使用前缀和:s[i] = A1 + A2 + … Ai例如A = [1, 2, 5, 4, 3]则 S = [1, 3, 8, 12, 15]我们要计算Ai + Ai+1 + … Aj,则需计算S[j] – S[i-1]。 例如A2 + A3 + A4 = 2 + 5 + 4 = 11。利用前缀和:S[4] – S[1] = 12 – 1 = 11为了使用方便,我们一般令S[0] = 0,这样A1+A2+A3 = S[3] – S[0] = 8 – 0 = 8. *//*———————————————————————————————————————————————————————————题目:K倍区间问题描述: 给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。 你能求出数列中总共有多少个K倍区间吗?第一行包含两个整数N和K。(1 <= N, K <= 100000) 以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)例子:A = [1, 2, 3, 4, 5], K = 2答案是6:[1, 2, 3], [1, 2, 3, 4], [2], [2, 3, 4, 5], [3, 4, 5], [4] 数据规模与约定 思路:基本思路:枚举起点Ai和终点Aj,计算部分和S = Ai + Ai+1 + Ai+2 + … Aj如果S是K倍数,ans++for i = 1 … N: for j = i … N: s = 0 for t = i … j: s += A[t] if s % K == 0: ans++————————————————————————————————————————————————————————————*///#include #include #include using namespace std;#define ll long longint N,K;ll ans = 0;int a[100000+5]; int S[100000+5]; //S[i]表示a[1]到a[i]的和int cnt[100000+5]; //cnt[i]表示S模K为i的数的个数 void solve(){ for(int i=1; i<=N; ++i) { S[i] = (S[i-1] + a[i])%K; ans += cnt[S[i]]; cnt[S[i]]++; } cout< cnt;int main() { s[0] = 0; cnt[0] = 1; for(int i = 1; i <= n; i++) { s[i] = (s[i-1] + a[i]) % k; cnt[s[i]]++; } long long ans = 0; for(int i = 0; i < k; i++) { ans += (long long)(cnt[i]) * (cnt[i] - 1) / 2; } cout << ans << endl; return 0;} /*———————————————————————————————————————————————————————————题目:2018年日志统计问题描述: 小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:ts id 表示在ts时刻编号id的帖子收到一个"赞"。 现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。 给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。   ————————————————————————————————————————————————————————————*///#include#include#includeusing namespace std;int n,d,k,ts,id;vector ve[1010];int ans[1010];int judge(int x){ int len=ve[x].size(); if(len=k) { //时间间隔小于d if(ve[x][r]-ve[x][l]>n>>d>>k; for(int i=1;i<=n;i++) { cin>>ts>>id; ve[id].push_back(ts); } int cnt=0; for(int i=1;i<=1010;i++) { if(judge(i)) { ans[++cnt]=i; } } for(int i=1;i<=cnt;i++) { cout<#include #define N 100004long int n,anmin=0,cnmax=0,tn=0;long int an[N],cn[N];void swp(long int *t,long int x,long int y) { long int tem=t[x]; t[x]=t[y]; t[y]=tem; }long int qp(long int t[N],long int r,long int l){ long int x=t[r]; long int i=r; long int j=l+1; while(1) { while(t[++i]x); if(ia[i]||i==1)anmin=a[i]; } for(i=1;i<=n;i++) scanf("%ld",&b[i]); for(i=1;i<=n;i++){ scanf("%ld",&c[i]); if(cnmax=anmin)d--; while(cn[d1]==0&&d1<=cnmax)d1++; sum+=an[d]*cn[d1]; } printf("%ld\n",sum); return 0;}/*———————————————————————————————————————————————————————————题目:哪天返回问题描述: 小明被不明势力劫持。后莫名其妙被扔到x星站再无问津。小明得知每天都有飞船飞往地球,但需要108元的船票,而他却身无分文。他决定在x星战打工。好心的老板答应包食宿,第1天给他1元钱。并且,以后的每一天都比前一天多2元钱,直到他有足够的钱买票。请计算一下,小明在第几天就能凑够108元,返回地球。————————————————————————————————————————————————————————————*///#include int main(){ int n=0,i,s=0,c=0; for(i=1; i<100; i+=2) { s=s+i; n++; if(s>=108) { printf("%d %d",s,n); break; } } return 0;} /*———————————————————————————————————————————————————————————题目:猴子分香蕉问题描述: 5只猴子是好朋友,在海边的椰子树上睡着了。这期间,有商船把一大堆香蕉忘记在沙滩上离去。第1只猴子醒来,把香蕉均分成5堆,还剩下1个,就吃掉并把自己的一份藏起来继续睡觉。第2只猴子醒来,重新把香蕉均分成5堆,还剩下2个,就吃掉并把自己的一份藏起来继续睡觉。第3只猴子醒来,重新把香蕉均分成5堆,还剩下3个,就吃掉并把自己的一份藏起来继续睡觉。第4只猴子醒来,重新把香蕉均分成5堆,还剩下4个,就吃掉并把自己的一份藏起来继续睡觉。第5只猴子醒来,重新把香蕉均分成5堆,哈哈,正好不剩!请计算一开始最少有多少个香蕉。需要提交的是一个整数,不要填写任何多余的内容————————————————————————————————————————————————————————————*///#include int main(){ int i=6;//要分5次所以从6开始计算 while(true) { if(i%5==1)//第一次分会多出一个 { int x1=i-(i-1)/5;//第一次均分后 都会少一份被拿走 x1=x1-1;//对了,不能忘记每次多出来的香蕉也被醒过来的猴子偷吃了 if(x1%5==2) { int x2=x1-(x1-2)/5; x2=x2-2; if(x2%5==3) { int x3=x2-(x2-3)/5; x3=x3-3; if(x3%5==4) { int x4=x3-(x3-4)/5; x4=x4-4; if(x4%5==0 && x4!=0)//要确保到最后一个猴子醒过来的时候还有香蕉!且正好可以被均分 { printf("%d \n",i); break; } } } } } i++; } return 0;}//结果:3141/*———————————————————————————————————————————————————————————题目:第几个幸运数问题描述: 到x星球旅行的游客都被发给一个整数,作为游客编号。x星的国王有个怪癖,他只喜欢数字3,5和7。国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。我们来看前10个幸运数字是:3 5 7 9 15 21 25 27 35 45因而第11个幸运数字是:49小明领到了一个幸运数字 59084709587505,他去领奖的时候,人家要求他准确地说出这是第几个幸运数字,否则领不到奖品。请你帮小明计算一下,59084709587505是第几个幸运数字。需要提交的是一个整数,请不要填写任何多余内容。————————————————————————————————————————————————————————————*///思路:用1作为初始值,先将1分别乘上3、5、7得到3、5、7,再将这三个数分别乘上3、5、7得到9、15、21;15、25、35;21、35、49,以此类推。需要注意的是,为了得到59084709587505的正确序号,我们得保证前面依次乘出来的数要从小到大排序,并且不能重复,于是就要用的priority_queue和set。代码:#include#include#include#include#include#include#include#include#include#include#includeusing namespace std; priority_queue,greater > q;set s; int main(){ int ans=-1; q.push(1); s.insert(1); while(1) { long long n=q-(); q.pop(); ans++; if(n==59084709587505) break; for(int i=3;i<=7;i+=2) { long long t=n*i; if(!s.count(t)) { q.push(t); s.insert(t); } } } cout<#includeusing namespace std;char map[10][10];bool visited[10][10];int Count = 0;void DFS(int i, int j) { if (i<0 || i>9 || j<0 || j>9) {//出界符合题意 Count++; return; } if (visited[i][j]) { return ; } visited[i][j] = true;//标记走过的路 if (map[i][j] == 'U') { DFS(--i, j); } else if (map[i][j] == 'D') { DFS(++i, j); } else if (map[i][j] == 'L') { DFS(i, --j); } else { DFS(i, ++j); }}int main() { for (int i = 0; i<10; i++) for (int j = 0; j<10; j++) { cin >> map[i][j]; } for (int i = 0; i<10; i++) { for (int j = 0; j<10; j++) { memset(visited, false, sizeof(visited)); DFS(i, j); } } cout << Count; return 0;}/*———————————————————————————————————————————————————————————题目:凑算式问题描述: B DEFA + --- + ------- = 10 C GHI 这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。比如:6+8/3+952/714 就是一种解法,5+3/1+972/486 是另一种解法。这个算式一共有多少种解法?————————————————————————————————————————————————————————————*///int a[9]; bool used[10] = {false}; int ans = 0;void dfs(int x) { if(x == 9) { if(a[2] == 0 || a[6] == 0 || a[3] == 0) return; if(fabs(a[0] + 1.0*a[1]/a[2] + 1.0*(a[3]*100+a[4]*10+a[5])/(a[6]*100+a[7]*10+a[8])-10) < 1e-6) ans++; return; } for(int i = 1; i < 10; i++) if(!used[i]) { a[x] = i; used[i] = true; dfs(x+1); used[i] = false; }}int main() { dfs(0); cout << ans << endl ; return 0;}/*———————————————————————————————————————————————————————————题目:搭积木问题描述: 小明最近喜欢搭数字积木,一共有10块积木,每个积木上有一个数字,0~9。搭积木规则:每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。最后搭成4层的金字塔形,必须用完所有的积木。下面是两种合格的搭法: 0 1 2 3 4 56 7 8 9 0 3 1 7 5 29 8 6 4 请你计算这样的搭法一共有多少种?关键问题:怎么判断一定比下面的两个积木数字小————————————————————————————————————————————————————————————*///思路一:Hardcodeint a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};int ans = 0;bool ok() { return a[0] < a[1] && a[0] < a[2] && a[1] < a[3] && a[1] < a[4] && a[2] < a[4] && a[2] < a[5] && a[3] < a[6] && a[3] < a[7] && a[4] < a[7] && a[4] < a[8] && a[5] < a[8] && a[5] < a[9];}int main(){ for(int i = 0; i < 10*9*8*7*6*5*4*3*2; i++) { if(ok()) ans++; next_permutation(a, a+10); } cout << ans << endl; return 0;}//思路二:一维数组转二维矩阵int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};int ans = 0;bool ok() { int b[4][4]; int k = 0; for(int i = 0; i < 4; i++) for(int j = 0; j <= i; j++) b[i][j] = a[k++]; for(int i = 0; i < 3; i++) for(int j = 0; j <= i; j++) if(b[i][j] >= b[i+1][j] || b[i][j] >= b[i+1][j+1]) return false; return true;}int main() { for(int i = 0; i < 10*9*8*7*6*5*4*3*2; i++) { if(ok()) ans++; next_permutation(a, a+10) ; } cout << ans << endl ; return 0 ;}/*———————————————————————————————————————————————————————————题目:方格填数问题描述: 如下的10个格子 +--+--+--+ | | | |+--+--+--+--+| | | | |+--+--+--+--+| | | |+--+--+--+入0~9的数字。要求:连续的两个数字不能相邻。(左右、上下、对角都算相邻)一共有多少种可能的填数方案?//思路分析如何枚举?给格子编号 +--+--+--+ | 0| 1| 2|+--+--+--+--+| 3| 4| 5| 6|+--+--+--+--+| 7| 8| 9|+--+--+--+如何处理相邻?Hardcode:int adj[10][10] = { {0, 1, 0, 1, 1, 1, 0, 0, 0, 0}, {1, 0, 1, 0, 1, 1, 1, 0, 0, 0}, {0, 1, 0, 0, 0, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 1, 0, 0, 1, 1, 0}, {1, 1, 0, 1, 0, 1, 0, 1, 1, 1}, {1, 1, 1, 0, 1, 0, 1, 0, 1, 1}, {0, 1, 1, 0, 0, 1, 0, 0, 0, 1}, {0, 0, 0, 1, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 1, 1, 1, 0, 1, 0, 1}, {0, 0, 0, 0, 1, 1, 1, 0, 1, 0}};————————————————————————————————————————————————————————————*///#includeusing namespace std ;//给格子编号int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//处理相邻bool adj(int x, int y) { int rx = x / 4, cx = x % 4, ry = y / 4, cy = y % 4 ; return abs(rx - ry) <= 1 && abs(cx - cy) <= 1 ;}bool ok() { for(int i = 0; i < 9; i++) { if(adj[a[i]][a[i+1]]) return false; } return true;} int main(){ int ans = 0; for(int i = 0; i < 10*9*8*7*6*5*4*3*2*1; i++) { if(ok()) ans++; next_permutation(a, a+10); } cout << ans << endl; return 0;}/*———————————————————————————————————————————————————————————题目:寒假作业问题描述: 现在小学的数学题目也不是那么好玩的。看看这个寒假作业: □ + □ = □ □ - □ = □ □ × □ = □ □ ÷ □ = □每个方块代表1~13中的某一个数字,但不能重复。比如: 6 + 7 = 13 9 - 8 = 1 3 * 4 = 12 10 / 2 = 5以及: 7 + 6 = 13 9 - 8 = 1 3 * 4 = 12 10 / 2 = 5就算两种解法。(加法,乘法交换律后算不同的方案) 你一共找到了多少种方案?注意÷需要能除尽————————————————————————————————————————————————————————————*//*思路: 确定枚举的变量 a[0] + a[1] = □ a[2] – a[3] = □ a[4] × a[5] = □ a[6] ÷ a[7] = □?*/#includeusing namespace std ;int a[8]; bool used[14] = {false}; int ans = 0 ;void dfs(int x) { int y = 0 ; if(x == 8) { if(a[6] % a[7] != 0) return ; y = a[6] / a[7] ; if(y >= 1 && y <= 13 && !used[y]) ans++ ; return ; } if(x == 2) y = a[0] + a[1] ; if(x == 4) y = a[2] - a[3] ; if(x == 6) y = a[4] * a[5] ; if((y != 0) && (y < 1 || y > 13 || used[y])) return ; used[y] = true ; for(a[x] = 1; a[x] < 14; a[x]++) if(!used[a[x]]) { used[a[x]] = true ; dfs(x+1); used[a[x]] = false ; } used[y] = false ;}int main() { dfs(0) ; cout << ans << endl ; return 0 ;}/*———————————————————————————————————————————————————————————题目:2018年全球变暖问题描述: 你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:........##.....##........##...####....###........其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。 例如上图中的海域未来会变成如下样子:................................#................请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。 ————————————————————————————————————————————————————————————*///思路深搜并且标记统计原来的岛屿数目以及被淹没后#include#include#include#includeusing namespace std;bool flag;//标记是否岛屿沉没char a[1010][1010];//地图保存int cnt=0;//统计周围#的数目int n;//int d[4][2]= {1,0,-1,0,0,1,0,-1};//枚举方向的数组int ans=0;//被淹没后的岛屿个数int res_ans=0;//没被淹没的岛屿的个数void dfs(int x,int y)//回溯{ if(a[x][y]!='#')//如果这个点被标记成已经探索的岛屿内容或者是海洋,那么就返回 return ; if(x>=n||x<0||y>=n||y<0)//如果越界了也是返回 return ; if(flag==false)//如果还没确定不会被淹没,即当前是被淹没状态 { cnt=0;//统计这个岛屿的当前点坐标x,y的上下左右的四个点是不是都是'#',如果确实是这样的,那么为我们就可以确定这个岛屿不会被淹没,我们姑且叫这样的点叫做不可淹没点,,那么只要一个岛屿有一个这样的点就一定不会被淹没 for(int i=0; i<4; i++)//枚举四个方向 { int tx=x+d[i][0]; int ty=y+d[i][1]; if(tx=0&&ty=0&&a[tx][ty]!='.')//假设枚举的四周的点不会超界并且不是海洋,那么cnt数目+1 { cnt++; } } if(cnt==4)//如果四周的点都是这样的那么这个点就是不可淹没点 { ans++;//最后不会被淹没的点+! flag=true;//这个岛屿标记已经确定,当前岛屿是不可以被淹没的,所以当回溯这个岛屿其他点的时候就不用再来检查了,因为一个岛屿有一个这样的不可淹没点就够了 } } a[x][y]='*';//对于已经探索的岛屿的内容标记成'*', for(int i=0; i<4; i++) { int tx=x+d[i][0]; int ty=y+d[i][1]; dfs(tx,ty);//对于四个方向进行回溯岛屿的所有点 }}int main(){ cin>>n; for(int i=0; iusing namespace std;typedef long long ll;#define inf 0x3f3f3f#define mem(a,b) memset( a,b,sizeof a)string s1,s2;map m;struct node{ string s; int step; node(string ss,int tp) { s=ss; step=tp; }};queue q;int main(){ std::ios::sync_with_stdio(false); cin>>s1>>s2; int l=s1.size(); q.push(node(s1,0)); while(!q.empty()) { node t=q.front(); q.pop(); if(t.s==s2) return cout<#include#includeusing namespace std;const int MAX_N = 101;char s[MAX_N][MAX_N];int book[MAX_N][MAX_N];int N, startX, startY, endX, endY;int MIN1 = 99999;bool f;int C = 0;int next[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0}};int getX(char c) { for (int i = 0; i< N; i++) { for (int j = 0; j < N; j++) { if (s[i][j] == c) return i; } }}int getY(char c) { for (int i = 0; i< N; i++) { for (int j = 0; j < N; j++) { if (s[i][j] == c) return j; } }}void dfs(int x, int y, int step) { // 四种走法 上下左右 for (int i = 0; i < 4; i++) { int tx = x + next[i][0]; int ty = y + next[i][1]; // 判断是否越界 if (tx < 0 || tx > N || ty < 0 || ty > N) continue; // 判断交替 if (s[x][y] == '+') f = true; else if (s[x][y] == '-') f = false; if (tx == endX && ty == endY) { // 更新最小值 if (step < MIN1) MIN1 = step; return; //返回 } // 判断是否是障碍物或者已经走过 if (f && C > 0) { if (book[tx][ty] == 0 && s[tx][ty] == '-') { C++; book[tx][ty] = 1; dfs(tx, ty, step+1); book[tx][ty] = 0; } } else if(!f && C > 0) { if (book[tx][ty] == 0 && s[tx][ty] == '+') { C++; book[tx][ty] = 1; dfs(tx, ty, step+1); book[tx][ty] = 0; } } else { if (book[tx][ty] == 0) { C++; book[tx][ty] = 1; dfs(tx, ty, step+1); book[tx][ty] = 0; } } }}int main() { freopen("in.txt", "r", stdin); scanf("%d", &N); getchar(); for (int i = 0; i< N; i++) { for (int j = 0; j < N; j++) { scanf("%c", &s[i][j]); getchar(); } } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) book[i][j] = 0; } startX = getX('A'); startY = getY('A'); endX = getX('B'); endY = getY('B'); book[startX][startY] = 1; dfs(startX, startY, 1); if (MIN1 == 99999) MIN1 = -1; cout << MIN1 << endl; return 0;}/*———————————————————————————————————————————————————————————题目:乘积尾0问题描述: 如下的10行数据,每行有10个整数,请你求出它们的乘积的末尾有多少个零?5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070 2287 1453 9899 1486 5722 3135 1170 4014 5510 5120 729 2880 9019 2049 698 4582 4346 4427 646 9742 7340 1230 7683 5693 7015 6887 7381 4172 4341 2909 2027 7355 5649 6701 6645 1671 5978 2704 9926 295 3125 3878 6785 2066 4247 4800 1578 6652 4616 1113 6205 3264 2915 3966 5291 2904 1285 2193 1428 2265 8730 9436 7074 689 5510 8243 6114 337 4096 8199 7313 3685 211 注意:需要提交的是一个整数,表示末尾零的个数。不要填写任何多余内容。我们对每一个数进行因式分解,假设我们有n个数,统计这n个数的质因子中一共有多少个2和5;显然我们一个2和一个5能组成一个10,我们要知道这些2和5能组成多少个10即可;————————————————————————————————————————————————————————————*///#include int data[] ={5650,4542,3554,473,946,4114,3871,9073,90,4329,2758,7949,6113,5659,5245,7432,3051,4434,6704,3594,9937,1173,6866,3397,4759,7557,3070,2287,1453,9899,1486,5722,3135,1170,4014,5510,5120,729,2880,9019,2049,698,4582,4346,4427,646,9742,7340,1230,7683,5693,7015,6887,7381,4172,4341,2909,2027,7355,5649,6701,6645,1671,5978,2704,9926,295,3125,3878,6785,2066,4247,4800,1578,6652,4616,1113,6205,3264,2915,3966,5291,2904,1285,2193,1428,2265,8730,9436,7074,689,5510,8243,6114,337,4096,8199,7313,3685,211};struct node { int a2 , a5; //用来储存每个数质因子中2和5的个数; };node count(int num); //计算num 质因子中2和5的数量,并存在结构体中 int main(){ int len = sizeof(data) / sizeof(int); int a5 = 0,a2 = 0; for(int i = 0;i#include#include#includetypedef long long LL;LL GOD;int require,base;LL transform(char *num){ int i; LL sum=0,nowbase=1; for(i=strlen(num)-1; i>=0; i--) { if(isdigit(num[i])) sum+=(num[i]-'0')*nowbase; else sum+=(num[i]-'A'+10)*nowbase; nowbase*=base; } return sum;}int notransform(char *num){ int sp=0; sscanf(num,"%d",&sp); return sp;}char* retransform(LL num){ static char ans[100]={0}; int index=1; if(!num) ans[index++]='0'; while(num) { int temp=(num%base); if(temp<10) ans[index++]=temp+'0'; else ans[index++]=temp-10+'A'; num/=base; } ans[0]=index-1; return ans;}void runorder(char *str){ char Torder[9][10]={"NUM","ADD","SUB","MUL","DIV","MOD","CHANGE","EQUAL","CLEAR"}; char sp[10]; sscanf(str,"%s",sp); char spnum[100]={0}; if(strlen(sp)!=strlen(str)) sscanf(str,"%*s%s",spnum); int i,j; char *temp=NULL; for(i=0;i<9;i++) { if(!strcmp(sp,Torder[i])) { switch(i) { case 0: if(require==0) GOD=transform(spnum); else { if(require==1) GOD+=transform(spnum); if(require==2) GOD-=transform(spnum); if(require==3) GOD*=transform(spnum); if(require==4) GOD/=transform(spnum); if(require==5) GOD%=transform(spnum); require=0; } break; case 1: require=1;break; case 2: require=2;break; case 3: require=3;break; case 4: require=4;break; case 5: require=5;break; case 6: base=notransform(spnum);break; case 7: temp=retransform(GOD); for(j=temp[0];j>=1;j--) putchar(temp[j]); putchar('\n'); break; case 8: GOD=0; require=0; } } }}int main(int argc,char **argv){ int cnt; scanf("%d",&cnt); base=10,require=0; while(cnt--) { char order[30]; scanf("%*c%[^\n]",order); runorder(order); } return EXIT_SUCCESS;}/*———————————————————————————————————————————————————————————题目:乘积最大问题描述: 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:有一个数字串:312, 当N=3,K=1时会有以下两种分法: 3*12=36 31*2=62这时,符合题目要求的结果是:31*2=62现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。输入格式  程序的输入共有两行:  第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)  第二行是一个长度为N的数字串。输出格式  输出所求得的最大乘积(一个自然数)。样例输入4 21231样例输出62解答:动态规划dp[j][k] 代表前J位中插入了K个乘号能够达到的最大值则状态转移方程为dp[j][k]=max{dp[j][k],dp[i][k-1]*product(k+1,j)};i是从k变到(j-1);前J位插入K个乘号所能达到最大的值等于(前i位插入了K-1的乘号与第i+1位到第J位表示的数(product(k+1,j))的乘积)的最大值。————————————————————————————————————————————————————————————*///#include#include#include#define max(x,y) ((x)>(y)?(x):(y))unsigned long long dp[41][31]={0};char str[41];int a[41];unsigned long long product(int j,int k)//计算第j位到第K位组成的数 { int i; unsigned long long sum=0; for(i=j;i<=k;i++) sum=sum*10+a[i]; return sum; }int main(){ int n,K; scanf("%d%d",&n,&K); scanf("%s",str); int i,j,k; for(i=0;iavg的人的付费平均值,或许又会有人付不起这个新的avg,就是nowavg,所以循环这个过程,直到没有人付不起被抬高的avg。这样的话那些都能付得起新的avg的有钱人付的钱均相等,都是新的avg。————————————————————————————————————————————————————————————*///#include#include#include#include#include#define ll long long#define num ch-'0'#define ld long double #define rep(i,a,b) for(register int i=(a);i<=(b);++i)using namespace std;const int N=500010;ll cnt,n,m,a[N];ld b[N],ans=0,avg,tot,nowavg;inline void get(ll &res){ char ch;bool flag=0; while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); for(res=num;isdigit(ch=getchar());res=res*10+num); (flag)&&(res=-res);}int main() { get(n),get(m); rep(i,1,n) get(a[i]); sort(a+1,a+n+1); nowavg=avg=1.0*m/n; tot=0; rep(i,1,n) { if(a[i]=nowavg) { ans+=(nowavg-avg)*(nowavg-avg)*(n-i+1); break; } --i; } } ans/=(ld)n; ans=sqrt(ans); printf("%.4Lf",(ld)ans); return 0;}

Talk is cheap. Show me the code

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Eclipse logo集成开发环境 Eclipse
下一篇:python代码运行显示PC参数
相关文章

 发表评论

暂时没有评论,来抢沙发吧~