還是有很多不足的,模擬思維還需加強,還有一直被詬病的圖論
一:6的個數;
水題,沒有過多的花裡胡哨,手算(不太建議)或者程式碼模擬即可
參考程式碼如下:
1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int n=2021, num = 0; 5 int main() 6 { 7 ios::sync_with_stdio(false); 8 for (register int i = 1; i <= 2021; i++) 9 { 10 int num1=i; 11 while (num1) 12 { 13 if (num1 % 10==6)num++; 14 num1 /= 10; 15 } 16 } 17 cout<<num; 18 return 0; 19 }
二:小明的作業;
不好意思,錯了,我是弱雞;
三:斐波那契(模擬思維的具體體現)
提供兩種思路
1.常見的gcd寫法,即gcd的遞迴寫法,也有相應的輾轉相除法,不在贅敘;
1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int a[100]={0,1,1}; 5 int b[100]; 6 long long fenzi; 7 long long fenmu; 8 long long gcd(long long a,long long b)//手寫gcd函式 9 { 10 if(b==0) return a; 11 return gcd(b,a%b); 12 } 13 int main() 14 { 15 for(register int i=3;i<=18;i++) 16 { 17 a[i]=a[i-1]+a[i-2]; 18 } 19 for(int i=1;i<=13;i++) 20 { 21 b[i]=a[i]*a[i+1];//分母 22 } 23 fenzi=1;//分子 24 fenmu=1;//分母 25 for(int i=2;i<=13;i++) 26 { 27 fenzi=fenzi*b[i]+1*fenmu; 28 fenmu=fenmu*b[i]; 29 long long temp=gcd(fenzi,fenmu);//兩者的最大共約數 30 fenzi=fenzi/temp;//通分 ,不通分的後果就是程式不走或者直接爆 31 fenmu=fenmu/temp;//通分 32 } 33 cout<<fenzi<<"/"<<fenmu<<endl; 34 return 0; 35 }
還要一種是關於STL庫裡好像是直接能寫一種gcd函式,具體請看這篇https://blog.csdn.net/qq_44731019/article/details/109478391(轉載),然後網上給出的程式碼思路也是和手寫gcd大致的,這個相較於手寫省去了很多麻煩,學到了;
摘自網上程式碼:
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int main() 5 { 6 long long f[14]; 7 f[0]=1; 8 f[1]=1; 9 for(int i=2;i<=13;i++) 10 { 11 f[i]=f[i-1]+f[i-2]; 12 } 13 long long up=1,down=1; 14 for(int i=1;i<13;i++) 15 { 16 long long x=f[i]*f[i+1]; 17 long long k=__gcd(x,down); 18 down*=(x/k); 19 up=up*(x/k)+down/x; 20 } 21 long long k=__gcd(up,down); 22 up/=k; 23 down/=k; 24 cout<<up<<'/'<<down<<endl; 25 return 0; 26 }
四:數列重組;
全排列肯定是少不了了,久違的next_permutation()肯定是要用的,
大體思路即是,在按照字典序的情況下,先判斷是否升序還是降序,並且對他們進行標記,然後滿足了三個開始重新標記,即進行下一輪的升序或者降序判斷,並且在滿足條件的時候加一
參考程式碼如下:
1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int a[20] = {2, 3, 3, 3, 5, 6, 6, 7, 7, 8}; 5 int ans;//放結果 6 int main(){ 7 ios::sync_with_stdio(false); 8 do{//next_permutaion()一般搭配do-while使用 9 bool flag1 = false, flag2 = false;//flag1表示之前是否出現遞增,flag2表示之前是否出現遞減 10 int cnt = 0;//計數器 11 for(register int i = 0;i<9; i++){//為社麼是小於9呢?因為有i+1,那這樣最後一個會越界,然後結果減半 12 if(a[i + 1] > a[i]){ 13 flag1 = true; 14 if(flag2){ 15 cnt ++; 16 flag2 = false; 17 flag1 = false;//flag1也要,因為當出現分割點後每次要從新的起點開始算,不受之前的區間影響了 18 19 } 20 21 } 22 else if(a[i + 1] < a[i]){ 23 flag2 = true; 24 if(flag1){ 25 cnt ++; 26 flag1 = false; 27 flag2 = false; 28 } 29 30 } 31 } 32 if(cnt <= 2) ans ++; 33 }while(next_permutation(a, a + 10));//按字典序排序 34 cout << ans; 35 return 0; 36 }
五:三角形個數
妥妥的好題,模擬思維的具體體現,這個題我是最後才做的,剛開始確實沒想到是等差數列;不過網上大多數人說用字首和求,我是弱雞,我不會(●ˇ∀ˇ●)
具體思路:
其實是找倒三角和正三角的個數,很不好找的其實
如果三角形的邊長是i
對於大三角形來說,如果正三角形是以1開始,到n-i+1結束的等差數列
而對於倒三角來說,是從1開始,到n-2i+1結束的;
1 #pragma GCC optimizee(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 const long long M=1e9+7; 5 int main() 6 { 7 ios::sync_with_stdio(false); 8 long long d=20210411,n; 9 long long sumz=0; 10 for(n=d;n>=1;n--) 11 sumz=(sumz+n*(n+1)/2)%M; 12 long long sumd=0; 13 for(n=d-1;n>=1;n-=2) 14 sumd=(sumd+n*(n+1)/2)%M; 15 printf("%lld\n",(sumz+sumd)%M); 16 return 0; 17 }
此外,本題特別鳴謝我身旁的zhy同學,如果他不和我說這個題是等差並且一直在堅持這個題,或許我就give up了;
六:字串
沒有什麼特殊的技巧,值得注意的是關於如何接受空格符的問題,這裡有兩種方法:
1.getline函式:http://c.biancheng.net/view/1345.html(轉載)
2.輸入的正則用法:https://blog.csdn.net/weixin_43469047/article/details/83753526(轉載);
不得不說長見識了
七:不會
八:友誼紐帶
唉,bfs我是很不擅長的,主要是用太多了STL關於佇列的操作,我當時都不知道怎麼做出來的,並且我的程式碼和網上標準答案大相徑庭,還是學習大佬的程式碼把
1 /*1.這題一開始我讀題目了,我以為的是把這些點全部連線起來所需要的最小邊數; 2 於是我用了並查集,只過了兩個點~ 3 2.後來發現題目是要求找出一個連通塊裡的任意兩點的距離,也就是連通塊的最大長度; 4 這樣的話我們就可以用BFS暴力搜尋所有節點,找出它們距其他節點的最遠距離`的最大值`; 5 當一次廣搜之後仍有節點未被訪問的則說明該圖不只有一個連通塊,輸出-1; 6 */ 7 #include<bits/stdc++.h> 8 using namespace std; 9 vector<int>G[2005]; 10 int vis[2005]; 11 int BFS(int x){ 12 memset(vis,0,sizeof(vis)); 13 queue<int>q; 14 q.push(x); 15 int ans=0; 16 while(!q.empty()){ 17 int f=q.front(); 18 q.pop(); 19 ans=max(ans,vis[f]); 20 for(int i=0;i<G[f].size();i++){ 21 int temp=G[f][i]; 22 if(vis[temp]==0){ 23 vis[temp]=vis[f]+1; 24 q.push(temp); 25 } 26 } 27 } 28 return ans; 29 } 30 int main(){ 31 int n,m; 32 cin>>n>>m; 33 for(int i=0;i<m;i++){ 34 int a,b; 35 cin>>a>>b; 36 G[a].push_back(b); 37 G[b].push_back(a); 38 } 39 int ans=0; 40 bool flag=true; 41 for(int j=1;j<=n;j++){ 42 ans=max(ans,BFS(j)); 43 for(int i=1;i<=n;i++) 44 if(vis[i]==0){ 45 flag=false;break; 46 } 47 } 48 if(flag) 49 cout<<ans<<endl; 50 else cout<<"-1"<<endl; 51 return 0; 52 }
轉載自:https://blog.csdn.net/alpha_xia/article/details/115703564?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~Rate-2.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~Rate-2.pc_relevant_antiscanv2&utm_relevant_index=4;
九:傳送門
這題我知道是克魯斯卡爾啊,我沒板子不會寫,太難了,寒假的時候最小生成樹就不會,主要是圖論太難了;
十:最後一個小時的時光,我當時腦子已經一片混沌了,這題我沒記錯的話應該是直接爆搜了,畢竟我也沒啥技巧了,只能搜了,唉;
思路是:列舉出每種獲勝情況,並且用check函式檢驗
然後接下來就是搜了
利用dfs來搜接下來下的一步棋的所有情況
當x==10是結束條件,其實在某一定程度上很像2n皇后,但又不像;
難度較高,高階的思維模擬題,如果沒有技巧建議深搜,畢竟搜可以混一部分的分數,運氣好的話還可以過
1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int p[100]; 5 int n; 6 int ans; 7 int check(int u)//檢查函式 8 { 9 if(p[0]+p[4]+p[8]==3*u||p[2]+p[4]+p[6]==3*u) 10 return 1; 11 if(p[0]+p[3]+p[6]==3*u||p[1]+p[4]+p[7]==3*u||p[2]+p[5]+p[8]==3*u) 12 return 1; 13 if(p[0]+p[1]+p[2]==3*u||p[3]+p[4]+p[5]==3*u||p[6]+p[7]+p[8]==3*u) 14 return 1; 15 else 16 return 0; 17 } 18 int dfs(int x)//深搜 19 { 20 if(x==10)//邊界條件 21 { 22 if(check(1)) return 1;//正常返回 23 if(check(-1)) return -1;//異常返回,此處也可以用bool判斷 24 return 0; 25 } 26 //開始模擬,怎麼這麼多模擬題 27 int t,lost=0,win=0,d=0; 28 if(x&1) t=1; 29 else t=-1; 30 for(int i=0;i<9;i++) 31 { 32 if(p[i]==0) 33 { 34 p[i]=t; 35 if(check(t)) win++; 36 else 37 { 38 int p=dfs(x+1); 39 if(p==t) 40 win++; 41 else if(p==0) d++; 42 else lost++; 43 } 44 p[i]=0; 45 } 46 } 47 if(win!=0) 48 return t; 49 else if(d!=0) 50 return 0; 51 else 52 return (-1*t); 53 } 54 int main() 55 { 56 ios::sync_with_stdio(false); 57 int t; 58 cin>>t; 59 while(t--) 60 { 61 ans=0; 62 memset(p,0,sizeof(p)); 63 cin>>n; 64 for(int i=1;i<=n;i++) 65 { 66 int x,y; 67 cin>>x>>y; 68 x--; 69 y--; 70 if(i&1) p[x*3+y]=1;//按位與運算,取 2進位制整數 i 的最低位,如果最低位是1 則得1,如果最低位是0 則得0。 奇數 i 的最低位 是1,偶數i 的最低位 是0。 71 else p[x*3+y]=-1; 72 } 73 ans=dfs(n+1); 74 if(ans==1) cout<<'X'<<endl; 75 else if(ans==0) 76 cout<<-1<<endl; 77 else cout<<'O'<<endl; 78 } 79 return 0; 80 }
總結:
通過這次模擬賽,很明確的是,對於難題,思維題,較難的模擬題,還有圖論尤其是最小生成樹方面還是有很多的不足
但是也得到了一些經驗:做不出來或者沒思路的時候搜也是一種不錯的選擇;
下一步加強搜尋的優化和訓練,學習一些自己在圖論上知識的空缺,加強模擬題以及思維題的訓練,即使難,多練,也會熟能生巧的;
道阻且長,興則將至,戒驕戒躁,任重道遠,早日成為自己想成為的人。
奔向遠方,加油加油!