一: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