生活随笔
收集整理的這篇文章主要介紹了
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];void dfs(int pos
,int sum
) {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
];}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();int n
;while(cin
>>n
) {int pos
=0;while(n
) {int t
=n
%26;if(t
==0) {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];
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
){ll temp
; cin
>>temp
; a
[i
] =temp
;}if(a
[i
]>ans
) {ans
=a
[i
];flag
=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
];
int visit
[maxn
];
using namespace std
;
int main()
{
int t
;cin
>>t
;while(t
--) {int n
;cin
>>n
;sum
[0]=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
);sort(sum
,sum
n
1);s0
=lower_bound(sum
,sum
n
1,s0
)-sum
;sn
=lower_bound(sum
,sum
n
1,sn
)-sum
;int l
=0,r
=n
;memset(visit
,0,sizeof(visit
));for(int i
=s0
;i
>=0;i
-=2) {a
[l
]=sum
[i
];visit
[i
]=1;}for(int i
=sn
;i
<=n
;i
=2) {a
[r
--]=sum
[i
];visit
[i
]=1;}for(int i
=0;i
<=n
;i
)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]));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ò),歡迎將生活随笔推薦給好友。