A题.[蓝桥杯 2013 省 B](补题)
题意: 用1-9的不重复不遗漏的数字组成a,b,c,使得a+b/c=n成立,则是一种方案,求整数n可以有多少种方案组成
思路: _数组a为1-9,用nextpermutation函数暴力枚举出所有1-9的不重复的组合,然后将他们分开组成a,b,c,由于数据是<=10^6,因此a只需要枚举到7位数。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,num[9]={1,2,3,4,5,6,7,8,9},ans;
int ZH(int s,int k ){
int ma=0;
for(int i=s;i<=k;i++){
ma=ma*10+num[i];
}
return ma;
}
int main(){
cin>>n;
do {
for (int i = 0; i <7; ++i) {
for (int j = i+1; j <8 ; ++j) {
int a,b,c;
a= ZH(0,i);
b=ZH(i+1,j);
c=ZH(j+1,8);
if((n-a)*c==b)
ans++;
}
}
} while (next_permutation(num,num+9));
cout<<ans;
return 0;
};
B [蓝桥杯 2013 省 AB] 错误票据.(补题)
题意:给出若干个数,其中只有一个值出现了两次,除一个值没出出现外其他值均连续
思路:注意到n很小,读入后排序然后枚举一边即可。此题有一个读入的问题不太好处理,可以用while(cin>>a)或者while(scanf("%d", %a) !=EOF),读到错误会自动跳出循环。
代码:
#include <bits/stdc++.h>
using namespace std;
int n,a[100009],x,dh,ch;
int main(){
cin>>n;
vector<int>ve;
while(cin>> x){
ve.push_back(x);
a[x]++;
}
for (int i = 1; i <=100000 ; ++i) {
if(a[i]==0&&a[i+1]>0&&a[i-1]>0)
dh=i;
if(a[i]>1)
ch=i;
}
cout<<dh<<' '<<ch;
}
C [蓝桥杯 2013 省 B] 翻硬币
题意: 两列硬币,每次操作可改变两个相邻硬币的正反,通过最小的n次把两列硬币变成完全相同
思路:题目保证一定有解,所以两个串的相同位置的不同情况一定出现偶数次,两两匹配算出花费即可
代码:
#include <bits/stdc++.h>
using namespace std;
string a,b;
int vis[1000],k,s;
int main(){
cin>>a>>b;
for (int i = 0; i <a.size() ; ++i) {
if(a[i]!=b[i])
vis[k]=i,k++;
}
for (int i = 0; i < k; i+=2) {
s+=(vis[i+1]-vis[i]);
}
cout<<s;
}
E.P8683 [蓝桥杯 2019 省 B] 后缀表达式(补题)
题意:给n个+号,m个-号,n+m+1个数,求他们组合的最大的后缀和
思路:括号是任意加的,因此减法可以变成加法,例如:a-(b-c)=a+c-b,有减号,必然有一个数是被减,那么我们用最小的那个数来做被减,最大-最小+其他所有数的绝对值即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll s,k;
int n,m;
int main(){
cin>>n>>m;
vector<int>a(n+m+1);
for (int i = 0; i <n+m+ 1 ; ++i) {
cin>>a[i];
}
if(!m){
for (int i = 0; i <n+m+1 ; ++i) {
s+=a[i];
}
cout<<s;
return 0;
}
sort(a.begin(),a.end());
s=a[n+m]-a[0];
for (int i = 1; i < n+m; ++i) {
s+=abs(a[i]);
}
cout<<s;
}
F.P8682 [蓝桥杯 2019 省 B] 等差数列
题意:给定一个等差数列的部分n个数,求包含这n个数的最短的等差数列的个数
思路:
思路1:
排序求这n个数的差放入数组,求这个数组所有数字的最小公因数,既是最小公差。
思路2:
由于n个数都是等差数列的一部分,因此他们的差最小值必定是满足最短数列的最小公差。
提示注意:如果方差d是0,那么最小的个数即是n,不能用(Amax-Amin)/d+1来求
代码:
思路1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100005],b[100005];
int n,d;
ll gcd(ll n,ll m);
ll gcds(ll b[], ll m);
int main(){
cin>>n;
for (int i = 0; i <n ; ++i) {
cin>>a[i];
}
sort(a,a+n,less<ll >());
for (int i = 0; i <n-1; ++i) {
b[i]=a[i+1]-a[i];
if(b[i]==0) {
cout <<n;
return 0;
}
}
ll k;
k=gcds(b,n-1);
cout<<(a[n-1]-a[0])/ k+1;
}
ll gcds(ll b[], ll m) {
ll tem = b[0];
for (int i = 1; i < m; i++) {
tem = gcd(tem,b[i]);
}
return tem;
}
ll gcd(ll n,ll m){
if(n % m == 0){
return m;
}
return gcd(m,n%m);
}
思路2
void solve() {
cin >> n;
vector<int> ve(n);
for (int i = 0; i < n; i++) {
cin >> ve[i];
}
std::sort(ve.begin(), ve.end());
a = inf;
for (int i = 0; i < n-1; ++i) {
a = min(ve[i+1] - ve[i], a);
}
if (a == 0) {
cout << n << '\n';
return;
}
cout << (ve.back() - ve[0]) / a + 1 << '\n';
}
G [蓝桥杯 2019 省 B] 特别数的和
题意:1-n中含有2,0,1,9任意数字的数字个数有多少?
思路:暴力枚举即可.
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int Num_number(int a) //求数字位数
{
int count=0;
if(a==0) count=1;
while(a!=0)
{
a/=10;
count++;
}
return count;
}
int main(){
ll n,s;
cin>>n;
for (ll i = 1; i <=n ; ++i) {
int k;
k= Num_number(i);
ll a=i;
int gg=0;
while(k--){
int x;
x=a%10;
a/=10;
if(x==2||x==0||x==1||x==9) {
gg=1;
break;
}
}
if(gg)
s+=i;
}
cout<<s;
}
H [蓝桥杯 2019 省 AB] 完全二叉树的权值
题意:给出一颗包含n个节点的完全二叉树,问哪一层的权值之和最大
思路:把树每一层的号码的临界节点找出,由于n<=10^5,因此找到30层即可,再把每个节点的权值的枚举即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int to[30];
ll s[30],ss;
int n,g[100005],z;
int main(){
to[0]=1;
for (int i = 1; i <=30 ; ++i) {
to[i]=to[i-1]*2;
}
cin>>n;
int k=1;
for (int i = 1; i <=n ; ++i) {
cin>>g[i];
}
for (int i = 1; i <= n; ++i) {
if(i<to[k]){
s[k]+=g[i];
}
if(i==to[k]) {
k++;
s[k]+=g[i];
}
}
for (int i = 1; i <=k ; ++i) {
if(s[i]>ss){
ss=s[i];
z=i;
}
}
cout<<z;
}
P8684 [蓝桥杯 2019 省 B] 灵能传输
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll s[300005];// //前缀和,还要存S0,各元素初值为0
ll x,z,t,n;
int main(){
cin>>t;
while (t--){
x=0;
cin>>n;
s[0]=0;
for (int i = 1; i <=n ; ++i) {
cin>>s[i];
s[i]+=s[i-1];
}
if(s[0]>s[n])
swap(s[0],s[n]);
ll s0=s[0],sn=s[n];
sort(s,s+n+1);
for (int i = 0; i <=n ; ++i) { // //找S0的位置(如果有多个值为S0,则任意取一个即可)
if(s[i]==s0){
s0=i;
break;
}
}
for (int i = 0; i <=n ; ++i) { //找Sn位置
if(s[i]==sn){
sn=i;
break;
}
}
vector<ll>a(n+1); //存处理后的前缀和序列
vector<bool>vis(n+1); //排序后每个数取出与否的标志
ll l=0,r=n;
for (ll i = s0; i >=0 ; i-=2) { //让S0跳着走到最小值S[0]
a[l++]=s[i];
vis[i]= true;
}
for (int i = sn; i <=n ; i+=2) { //让Sn反跳着走到最大值S[n]
a[r--]=s[i];
vis[i]= true;
}
for (int i = 0; i <=n ; ++i) { //剩下的数按顺序取
if(!vis[i])
a[l++]=s[i];
}
for (int i = 1; i <=n ; ++i) {
x= max(x,abs(a[i]-a[i-1]));
}
cout<<x<<'\n';
}
}