日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

2019年第十届蓝桥杯 C / C ++省赛 B 组真题题解

發(fā)布時(shí)間:2023/12/4 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019年第十届蓝桥杯 C / C ++省赛 B 组真题题解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

A: 組隊(duì)

輸入數(shù)據(jù)

編號(hào) 號(hào)位1 2 3 4 51 97 90 0 0 0 2 92 85 96 0 0 3 0 0 0 0 93 4 0 0 0 80 86 5 89 83 97 0 0 6 82 86 0 0 0 7 0 0 0 87 90 8 0 97 96 0 0 9 0 0 89 0 0 10 95 99 0 0 0 11 0 0 96 97 0 12 0 0 0 93 98 13 94 91 0 0 0 14 0 83 87 0 0 15 0 0 98 97 98 16 0 0 0 93 86 17 98 83 99 98 81 18 93 87 92 96 98 19 0 0 0 89 92 20 0 99 96 95 81

這題直接暴力就完事了,時(shí)間復(fù)雜度是20的5次方3.2E6,完全不會(huì)超時(shí)。

#include<iostream> #include<cstring> #include<algorithm> int visit[30],ans; using namespace std; struct people {int score[6]; }a[30];//存入同一個(gè)人的不同位置分?jǐn)?shù)void dfs(int pos,int sum) {//sum是當(dāng)前枚舉分?jǐn)?shù),pos是當(dāng)前枚舉的位置。if(pos==6) {ans=max(ans,sum);return ;}for(int i=1;i<=20;i ) {if(!visit[i]) {visit[i]=1;dfs(pos 1,sum a[i].score[pos]);visit[i]=0;}} } int main() {freopen("D:\\MY\\ce.txt","r",stdin);int t;ans=0;for(int i=1;i<=20;i ) {visit[i]=0;cin>>t;for(int j=1;j<=5;j )cin>>a[i].score[j];//這個(gè)人在第i位的分?jǐn)?shù)。}dfs(1,0);cout<<ans<<endl;return 0; }

最后答案是490.



B: 年號(hào)字串

這題是普通進(jìn)制的轉(zhuǎn)換,沒什么特別。
但是這里最重要的就是對(duì)于余數(shù)是零的要進(jìn)行處理,將其轉(zhuǎn)換為26,也就是Z。

#include<iostream> char a[30],ans[30]; using namespace std; void init() {for(int i=0;i<26;i )a[i 1]=(char)('A' i); } int main() {init();//初始化數(shù)組a,為A~Z。int n;while(cin>>n) {int pos=0;while(n) {int t=n%26;if(t==0) {//這一步中,對(duì)于余數(shù)是零的要轉(zhuǎn)化為26, t=26;//所以n要減去26,t要是26。 n-=26;}ans[pos ]=a[t];n/=26;}pos--;for(int i=pos;i>=0;i--)cout<<ans[i];cout<<endl;} return 0; }

答案是BYQ.



C: 數(shù)列求值

簡(jiǎn)單的遞歸,遞歸的時(shí)候磨去10000,保留最后4位數(shù)字,
但是這里的第20190324項(xiàng)可能過于大,單純的遞歸可能出不來(lái)結(jié)果。
~可以寫個(gè)記憶化。
~或者寫個(gè)for遞推跑出來(lái)。
~再高級(jí)一點(diǎn)就是矩陣快速冪了。

一、遞推寫法

#include<iostream> #define mood 10000 const int maxn=3e7; int a[maxn]={0,1,1,1}; using namespace std; int main() {for(int i=4;i<=20190324;i )a[i]=(a[i-1] a[i-2] a[i-3])%mood;cout<<a[20190324];return 0; }

二、記憶化遞歸

#include<iostream> #define mood 10000 const int maxn=3e7; int a[maxn]={0,1,1,1}; using namespace std; int dfs(int s) {if(a[s]) return a[s];a[s]=(dfs(s-1) dfs(s-2) dfs(s-3))%mood;return a[s]; } int main() {int n=20190324;printf("%d\n",dfs(n));return 0; }

這個(gè)試過了,跑不出來(lái),到十萬(wàn)多的時(shí)候就不行了
三、矩陣快速冪

#include<iostream> #define mood 10000 typedef long long ll; const int N=3; using namespace std; struct unit {ll a[N][N]; };unit the(unit a,unit b) {unit temp;for(int i=0;i<N;i )for(int j=0;j<N;j ) {temp.a[i][j]=0;for(int k=0;k<N;k )temp.a[i][j]=(temp.a[i][j] a.a[i][k]*b.a[k][j])%mood;}return temp; } int main() {int n;while(cin>>n) {if(n<=3) {cout<<1<<endl;continue;}unit ans={1,1,1,0,0,0,0,0,0};unit temp= {1,1,0,1,0,1,1,0,0};n-=3;while(n) {if(n&1) ans=the(ans,temp);temp=the(temp,temp);n>>=1;}cout<<ans.a[0][0]<<endl;}return 0; }

答案是4659.



D: 數(shù)的分解

#include<iostream> int ans[5]={1},sum; using namespace std; bool judge(int x) {while(x) {int t=x%10;if(t==2||t==4)return true;x/=10;}return false; } int main() {sum=0;int n=2019;for(int i=1;i<=n;i ) {if(judge(i))continue;for(int j=i 1;j<=n;j ) {if(i j>=n)break;if(judge(j)||i==j)continue;for(int k=j 1;k<=n;k ) {if(i j k>n)break;if(judge(k)||k==i||j==k)continue;if(i j k==n)sum ;}}}cout<<sum<<endl;return 0; }

直接暴力,一秒之內(nèi)出結(jié)果,但是要注意,i<j<k這樣才能保證,不會(huì)出現(xiàn)重復(fù)的情況,
這里的剪枝除了有 i<j<k,
還要注意當(dāng)i j>=n || i j k>n的時(shí)候要直接break出去。
本來(lái)想用dfs的遞歸的,但是一直剪枝出問題,出不來(lái)正確答案,就用這個(gè)for循環(huán)吧,

答案40785.



E: 迷宮
這個(gè)看參考我的上一篇博客,2019藍(lán)橋杯E題迷宮



F: 特別數(shù)的和

#include<iostream> using namespace std; bool judge(int x) {while(x) {int t=x%10;if(t==2||t==0||t==1||t==9)return true;x/=10;}return false; } int main() {int n;while(cin>>n) {int sum=0;for(int i=1;i<=n;i )if(judge(i))sum =i;cout<<sum<<endl;}return 0; }

一個(gè)循環(huán)加一個(gè)judge函數(shù)判斷數(shù)字是否含有2,0,1,9,
直接暴力,最大10000的測(cè)試樣例也是秒出,感覺比前面的題都更水。



G:完全二叉樹的權(quán)值


只要判斷當(dāng)前值的數(shù)組下標(biāo)是再哪一深度下就行了,第i層深度共有
2(i-1)個(gè)數(shù),這里的最大N<=100000,而217是131072,因此最多有17 1=18層

#include<iostream> #include<cstring> #include<cmath> typedef long long ll; ll a[20];//存放第i-1層的權(quán)值。 using namespace std; int main() {int n;while(cin>>n) {memset(a,0,sizeof(a));int l;for(int i=0;;i )//尋找最大深度層。if(n<=pow(2,i)) {l=i;break;}int pos=0,flag;ll ans=0;for(int i=0;i<=l;i ) {int longs=pow(2,i);for(int j=0;j<longs&&pos <n;j ){//讀入的操作,定義一個(gè)ll temp; //pos來(lái)保證讀入的數(shù)字個(gè)數(shù)cin>>temp; //與n是一樣的。a[i] =temp;}if(a[i]>ans) {ans=a[i];flag=i 1;//i是深度-1,所以真正深度應(yīng)該是i 1。}}cout<<flag<<endl;}return 0; }

H:等差數(shù)列

#include<iostream> #include<cmath> #include<algorithm> const int maxn=100010; int a[maxn]; using namespace std; int gcd(int x,int y) {if(y==0) return x;return gcd(y,x%y); } int main() {int n;while(cin>>n) {for(int i=0;i<n;i )cin>>a[i];sort(a,a n);int mina=a[0],maxa=a[n-1];for(int i=1;i<n;i )a[i-1]=a[i]-a[i-1];sort(a,a n-1);if(a[0]==0) {cout<<n<<endl;continue;}int step=a[0];for(int i=1;i<n-1;i ) {if(a[i]%step==0)continue;step=gcd(step,a[i]);}cout<<(maxa-mina)/step 1<<endl;}return 0; }

思路就是排序找對(duì)大的數(shù)和最小的數(shù),然后求得有序數(shù)的兩數(shù)之間的差,然后再找這些差之間的最大公因數(shù),
最后對(duì)求得的公因數(shù)進(jìn)行分類,
為零時(shí),就是常數(shù)列,所以長(zhǎng)度時(shí)n
不為零時(shí),長(zhǎng)度是(最大值減最小值)/所得的公因數(shù) 1。


寫了這一題,我真正明白了暴力杯這個(gè)稱號(hào),我都這么折騰了,他還是不超時(shí),以后有什么題不能優(yōu)化,直接暴力就完事了。



I:后綴表達(dá)式.

這道題就是有點(diǎn)難搞清楚n,m之間的關(guān)系,
假設(shè)m為零,答案很簡(jiǎn)單了,就是n 1個(gè)數(shù)相加。
當(dāng)m不為零時(shí),我們可以通過括號(hào)把所有的加號(hào)變成減號(hào)。所以這道題目就變成了,都是加號(hào),或者都是減號(hào)的問題,都是加號(hào)的問題上面已近考慮完了,
下面我們來(lái)考慮都是減號(hào)的問題,假設(shè)符號(hào)數(shù)時(shí)n m=L減號(hào)我們又可以通過加括號(hào)的方式,減去1~~L個(gè)數(shù),最少減去一個(gè)數(shù),最多減去L個(gè)數(shù),
于是這里有兩種特殊情況:
全是負(fù)數(shù),這里我們應(yīng)當(dāng)選取最大的負(fù)數(shù)不添加減號(hào)。
全是正數(shù),這里我們應(yīng)但選取最小的負(fù)數(shù)添加減號(hào)。

#include<iostream> typedef long long ll; const int maxn=2e5 10; ll a[maxn]; using namespace std; int main() {int n,m,l;cin>>n>>m;l=n m 1;ll minzheng=2000000000,maxfu=-2000000000;int zheng=0,fu=0;for(int i=0;i<l;i ) {cin>>a[i];if(a[i]>0) {zheng ;minzheng=min(minzheng,a[i]);}else if(a[i]<0) {fu ;maxfu=max(maxfu,a[i]); }}ll sum=0;if(m==0) {for(int i=0;i<l;i )sum =a[i];cout<<sum<<endl;}else {if(zheng==l) {for(int i=0;i<l;i )sum =a[i];cout<<sum-2*minzheng<<endl;}else if(fu==l) {for(int i=0;i<l;i )sum-=a[i];cout<<sum 2*maxfu<<endl;}else {for(int i=0;i<l;i ) {if(a[i]>0)sum =a[i];elsesum-=a[i];}cout<<sum<<endl;}}return 0; }

J: 靈能傳送.


菜雞的我看完這道題,就只會(huì)一個(gè)公式,( a[i-1] , a[i] , a[i-1] ) 轉(zhuǎn)變后變成了,
( a[i-1] a[i] , -a[i] , a[i 1] a[i] ),
然后想到要用前綴和或者差分,但還是不知道怎么寫。在B站看了yxc大佬的acwing視頻后,才明白如何寫

這道題大致分為兩種情況,在對(duì)情況進(jìn)行討論前,我們?cè)O(shè)定一些必要的約定。
數(shù)組讀入從1開始,一直到n,我們假設(shè)sum數(shù)組,sum[i]表示的是第i項(xiàng)的前綴和,設(shè)定s0=0,對(duì)上述公式的變換就可以寫成
(sum[i-1] , sum[i] , sum[i 1])變成(sum[i] , sum[i-1] , sum[i 1])
這里不難發(fā)現(xiàn),就是對(duì)下標(biāo)從 1~(n-1)的前綴和數(shù)組進(jìn)行交換,
—、第一種情況,如圖
這是最佳排列方式

假設(shè)最大的一項(xiàng)和最小的一項(xiàng)在第0個(gè)和第n個(gè)前綴和中。
要保證每?jī)身?xiàng)之間的差的絕對(duì)值最小,只有降序排列(最大在首,最小在尾。),或者升序排列(最小在首,最大在尾。)

二、第二種情況,如圖
這個(gè)是這種情況的最佳排列方式

最大和最小不一定都在首尾,先把選點(diǎn)排序,
這里我們的選點(diǎn)方式應(yīng)該是跳躍式的選點(diǎn)方式,如果,有兩個(gè)選點(diǎn)相連,那么一定有,兩個(gè)選點(diǎn)的間距大于二,那么最大值一定會(huì)比這兩個(gè)相連的選點(diǎn)的值更大,

我們把因?yàn)榈?個(gè)位置和第n個(gè)位置不能變,
我們把所有選點(diǎn)投射到y(tǒng)軸上,從數(shù)值為sum[0]的點(diǎn)開始向下,step=2的步長(zhǎng)選點(diǎn),從數(shù)值為sum[n]的點(diǎn)開始向上選點(diǎn),step也是2,然后把剩下的點(diǎn),按照升序補(bǔ)齊中間的一段。在對(duì)整個(gè)前綴和求出兩個(gè)之間絕對(duì)值最大的數(shù)。

#include<iostream> #include<cstring> #include<algorithm> #include<cmath> typedef long long ll; const int maxn=300010; ll sum[maxn],a[maxn];//sum是用存放排序前的前綴和數(shù)組,a是用來(lái)存放最后答案的前綴和數(shù)組。 int visit[maxn]; using namespace std; int main() { // freopen("D:\\MY\\ce.txt","r",stdin);int t;cin>>t;while(t--) {int n;cin>>n;sum[0]=0;//初始化第一個(gè)前綴和為0.for(int i=1;i<=n;i ) {ll t;cin>>t;sum[i]=sum[i-1] t;//存放初始前綴和。}ll s0=sum[0],sn=sum[n];if(s0>sn) swap(s0,sn);//交換順序,滿足s0<sn,便于運(yùn)算,sort(sum,sum n 1);//對(duì)前綴和數(shù)組排序,s0=lower_bound(sum,sum n 1,s0)-sum;//找到s0位于sum數(shù)組種的位置。sn=lower_bound(sum,sum n 1,sn)-sum;//找到sn位于sum數(shù)組中的位置。int l=0,r=n;memset(visit,0,sizeof(visit));for(int i=s0;i>=0;i-=2) {//從s0開始向下找數(shù)。a[l ]=sum[i];visit[i]=1;}for(int i=sn;i<=n;i =2) {//從sn開始向上招數(shù)。a[r--]=sum[i];visit[i]=1;}for(int i=0;i<=n;i )//用剩下的數(shù)補(bǔ)齊a數(shù)組。if(!visit[i])a[l ]=sum[i];ll ans=0;for(int i=1;i<=n;i )ans=max(ans,abs(a[i]-a[i-1]));//最后得到絕對(duì)值最大的數(shù),cout<<ans<<endl;}return 0; }

終于寫完了這篇題解了。
心得:
除了后兩道題是我真不會(huì)的,但是前面的題在oj上提交我也不能保證一次就對(duì)。還有就是,我這次真正明白了什么是藍(lán)橋杯,“暴力杯”了,藍(lán)橋杯的題實(shí)在不能優(yōu)化,就直接暴力完事了。

總結(jié)

以上是生活随笔為你收集整理的2019年第十届蓝桥杯 C / C ++省赛 B 组真题题解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。