一:B组蓝桥杯
A:有趣的数字
题意:
1到 1e5 中质数中包含5这个数字的质数个数
#include<bits/stdc++.h> using namespace std; bool pf(int n) { for(int i=2;i<=n/i+1;i++) { if(n%i==0) return false; } int m=n; while(m) { if(m%10==5)return true; m/=10; } return false; } int main () { int num=0; for(int i=3;i<100000;i++) { if(pf(i)) { cout<<i<<endl; num++; } } cout<<num<<endl; return 0; }
答案:3282
B:爬楼梯
题意:每次只能爬1,2,3,4个台阶,一共十个台阶,第五个和第七个台阶不能使用,到达第十个台阶的方法种类数。
#include<iostream> //简单递推题:就这几个手推就行 代码纯属糊弄 using namespace std; int f[20]; int main () { //最多能走四步则第一个台阶有一种情况,第二个台阶有1+第一个台阶的情况,第三个台阶有 1+第一个台阶情况+第二个台阶情况; f[0]=0; f[1]=1; f[2]=2;//1+1 f[3]=4;//1+2+1 f[4]=8;//1+2+4+1 f[5]=0;//1+2+4+1 for(int i=6;i<=10;i++) { if(i==7)continue; else f[i]=f[i-1]+f[i-2]+f[i-3]+f[i-4]; } cout<<f[10]; return 0; }
答案:72
把那个f[4]算成了7 傻狗一个
C:七巧板
题意:
在这个图中加五条直线分割成最多多少个区域。
emmm 我还以为是从一个空的三角形中画直线,那个 规律也很好找,每个直线尽量切割最多个区域即可,因为一条直线只能将一个区域分割成两个。
emm:再重复一遍 不管是空三角形还是里边有填充的三角形 都是计算下一条直线放到哪里能切割最多区域:下下条似乎是++,依次类推
这道题
第一条橙色直线 切6个区域,增加六个区域,下一条紫色直线切7个区域,增加7个区域,依次大胆类推
7+6+7+8+9+10=47 √
答案:47
然后我大胆类推 :空三角形 :1+1+2+3+4+5=16 hhhh(*^_^*)
把空三角形看作是一个平面来处理 似乎是这样子:
转一个不错的博客如下:
直线/折线/圆/三角形划分平面&直线切割球问题大总结(最多能划分多少区域)
D:苹果
题意:balabla cf改的 差不多意思
从左往右依次拿,尽量导致最后剩余的苹果更接近0,当下只考虑当前的一个达到最小,3个3个拿到最少之后,与后两个拼凑拿,一直到不能再小再往右遍历
#include<bits/stdc++.h> using namespace std; int a[(int)1e3]; int main () { int n; cin.tie(0); cin>>n; for(int i=0;i<n;i++) { cin>>a[i]; } int num=0; for(int i=0;i<n;i++) { num+=a[i]/3; if(a[i]>=3) a[i]%=3; if(i<=n-3) { int mi=min(min(a[i],a[i+1]),a[i+2]); num+=mi; a[i]-=mi; a[i+1]-=mi; a[i+2]-=mi; } } cout<<num<<endl; return 0; }
答案:62
E:方阵
题意:再n*n的方阵中,当A和B之间的连线上没有点为A和B可以互相见到,问有多少对这样的AheB 洛谷原题
#include<iostream> using namespace std; int gcd(int a,int b){return b==0 ?a:gcd(b,a%b);} long long dist(int a,int b){return a*a+b*b;} int main () { long long num=0; long long e=1e9+7; int n; long k; cin>>n>>k; k*=k; for(int i=1;i<n;i++) for(int j=1;j<n;j++) { if(gcd(i,j)==1&&dist(i,j)<=k) num=(num+(n-j)*(n-i)%e)%e; } num*=2; num+=(2*n*(n-1)%e); cout<<num<<endl; return 0; }
大体这么个意思 至于怎么化简那个式子 去洛谷看看
F:寻找重复项
题意:有一个数列 \{a_n\}{an},a_0=1a0=1,a_{i+1} =(A\times a_i+a_i \mod B)\mod Cai+1=(A×ai+aimodB)modC,请你编程求出这个数列第一次出现重复的项的标号。如果答案超过 20000002000000 输出 "-1"
(不加引号)
#include<iostream> #include<unordered_map> using namespace std; unordered_map<long long,int> p; int main () { long long num=1; long long A,B,C; cin>>A>>B>>C; p[1]=1; bool f=true; for(int i=1;i<=(int)2e6;i++) { num=(num*A+ num%B)%C; //cout<<num<<endl; if(p.count(num)) { f=false; cout<<i<<endl; break; } else p[num]=1; } if(f)cout<<-1<<endl; return 0; }
考察 unordered_map或者hash_map 标记
C++ 11标准中加入了unordered系列的容器。unordered_map记录元素的hash值,根据hash值判断元素是否相同。map相当于java中的TreeMap,unordered_map相当于HashMap。无论从查找、插入上来说,unordered_map的效率都优于hash_map,更优于map;而空间复杂度方面,hash_map最低,unordered_map次之,map最大。
对于STL里的map容器,count方法与find方法,都可以用来判断一个key是否出现,count统计的是key出现的次数,因此只能为0/1,而find基于迭代器实现,以mp.end()判断是否找到要求的key。
//摘抄:https://www.cnblogs.com/zzyoucan/p/9127660.html
I 最短路
题意:求1到所有点的距离和所有点回到1的距离最小值
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=20005,M=60005; LL sum=0; struct { int x,y; LL z; }a[M]; LL head[N],ver[M],Next[M],edge[M],d[N]; bool v[N]; int n,m,tot; priority_queue<pair<LL,int>>p; void add(int x,int y,LL z) { ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot; } void init() { tot=0; memset(head,0,sizeof(head)); memset(ver,0,sizeof(ver)); memset(Next,0,sizeof(Next)); memset(edge,0,sizeof(edge)); } void dijkstra() { memset(d,0x3f,sizeof(d)); memset(v,0,sizeof(v)); p.push(make_pair(0,1)); d[1]=0; while(p.size()) { int x=p.top().second; p.pop();//找到当前权值最小的x,o(long n),用x进行更新 if(v[x])continue; v[x]=1; for(int i=head[x];i;i=Next[i]) { LL y=ver[i],z=edge[i]; if(d[y]>d[x]+z) { d[y]=d[x]+z; p.push(make_pair(-d[y],y)); } } } } int main () { cin.tie(0); cout.tie(0); ios::sync_with_stdio(false); int t; cin>>t; while(t--) { init(); cin>>n>>m; for(int i=0;i<m;i++) { cin>>a[i].x>>a[i].y>>a[i].z; add(a[i].x,a[i].y,a[i].z); } dijkstra(); for(int i=1;i<=n;i++) sum+=d[i]; init(); for(int i=0;i<m;i++) { add(a[i].y,a[i].x,a[i].z); } dijkstra(); for(int i=1;i<=n;i++) sum+=d[i]; cout<<sum<<endl; sum=0; } return 0; }
从1开始跑一次单源最短路,求得1到所有点的权值。
重新建立邻接表,将所有有向路径反向,再跑一次单源最短路,这样求出的1到所有点的最短路就等效于所有点到1的最短路。
结构体储存路径 为了第二次跑最短路
邻接表储存 小根堆优化dijkstra
或者用spfa跑两遍
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=20005,M=60005; LL sum=0; struct { int x,y; LL z; }a[M]; LL head[N],ver[M],Next[M],edge[M],d[N]; bool v[N]; int n,m,tot; queue<int>p; void add(int x,int y,LL z) { ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot; } void init() { tot=0; memset(head,0,sizeof(head)); memset(ver,0,sizeof(ver)); memset(Next,0,sizeof(Next)); memset(edge,0,sizeof(edge)); } void spafa() { memset(d,0x3f,sizeof(d)); memset(v,0,sizeof(v)); d[1]=0; p.push(1); while(p.size()) { int x=p.front(); p.pop(); v[x]=0; for(int i=head[x];i;i=Next[i]) { LL y=ver[i],z=edge[i]; if(d[y]>d[x]+z) { d[y]=d[x]+z; if(!v[y])p.push(y); } } } } int main () { cin.tie(0); cout.tie(0); ios::sync_with_stdio(false); int t; cin>>t; while(t--) { init(); cin>>n>>m; for(int i=0;i<m;i++) { cin>>a[i].x>>a[i].y>>a[i].z; add(a[i].x,a[i].y,a[i].z); } spafa(); for(int i=1;i<=n;i++) sum+=d[i]; init(); for(int i=0;i<m;i++) { add(a[i].y,a[i].x,a[i].z); } spafa(); for(int i=1;i<=n;i++) sum+=d[i]; cout<<sum<<endl; sum=0; } return 0; }
区别不大:(spfa没使用小根堆优化)
上边是spfa 下边是 dijkstra