蓝桥杯2013年第四届C/C++ B组省赛习题题解

目录

第一题:高斯日记(日期计算)

第二题:马虎的算式(全排列)

第三题:第39级台阶(dfs)

第四题:黄金连分数(递推+大数运算)

第五题:前缀判断(枚举)

第六题:三部排序

第七题:错误票据

第八题:买不到的数目(打表找数学规律)

第九题:剪格子(困难)

第十题:大臣的旅费(树的直径+dfs)


题目来源:

2013年第四届C B组蓝桥杯省赛真题_元气算法的博客-CSDN博客


第一题:高斯日记(日期计算)

 

#include<iostream>
using namespace std;
int months[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
bool is_leap(int year)
{
	return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0));
}

int main()
{
	int year = 1777;
	int month = 4;
	int day = 30;

	int T = 8112;
	while (T--)
	{
		day++;
		if (month == 2)
		{
			if (is_leap(year)) months[2] = 29;//如果是闰年
		}
		if (day > months[month])//如果天数已经大于该月的天数时
		{
			if (month == 12)//如果该月是12月,那么就++年
			{
				year++;
				month = 1;//月份重新变为1
				day = 1;
			}
			else month++, day = 1;//否则只是月份++
		}
		months[2] = 28;//还原
	}

	printf("%d-%02d-%02d\n", year, month, day);//1799-07-16

	return 0;
}

第二题:马虎的算式(全排列)

 解析:

按题目所给形式模拟即可

#include<iostream>
using namespace std;

int main()
{
	int ans = 0;
	for(int a = 1; a <= 9; a++)
	{
		for(int b = 1; b <= 9; b++)
		{
			if(a!=b)
			for(int c =1; c <= 9; c++)
			{	
				if(c!=b&&c!=a)
				for(int d =1; d <= 9; d++)
				{	
					if(d!=c&&d!=b&&d!=a)
					for(int e =1; e <= 9; e++)
					{
						if(e!=d&&e!=c&&e!=b&&e!=a)
						{
							int left = (a*10+b) * (c*100+d*10+e);
							int right = (a*100+d*10+b) * (c*10+e); 
							if(left == right)
							{
								ans++;
							}
						}
					}
				}
			}
		}
	}
	cout << ans;
	return 0;	
}

第三题:第39级台阶(dfs)

 解析:

第四届蓝桥杯——第39级台阶_业余算法学徒的博客-CSDN博客

 dfs:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int ans;

// total表示当前走过的台阶数量,step表示当前的步数 
void dfs(int total, int step)    
{
    // 超出边界
	if(total > 39) return;
	
	if(total == 39)
	{
		// 步数为偶数,计数器加一 
		if(step % 2 == 0) ans ++; 
		return ;
	}
	
	// 每次迈步都有两种选择 
	dfs(total + 1, step + 1);
	dfs(total + 2, step + 1);
}

int main()
{
	dfs(0, 0);
	cout << ans << endl;
	return 0;
} 

dp:

#include <iostream>
using namespace std;

int f[40][40];

int main()
{
	f[1][1] = 1;
	f[1][2] = 0;
	f[2][1] = 1;
	f[2][2] = 1;
	
	for (int i = 3; i <= 39; i ++)
	{
		f[i][1] = f[i - 1][2] + f[i - 2][2];
		f[i][2] = f[i - 1][1] + f[i - 2][1];
	}
		
	cout << f[39][2] << endl;
	return 0;	
}

第四题:黄金连分数(递推+大数运算)

黄金连分数(斐波那契数列、大数运算)正确解法_WinOneKey的博客-CSDN博客_黄金连分数


第五题:前缀判断(枚举)

char *prefix(char *haystack_start,char *needle_start)
{ 
	char *haystack=haystack_start;
	char *needle=needle_start;
	while(*haystack&&*needle)
	{
		if(_____________________) return NULL;  //填空位置
	}
	if(*needle) return NULL;
	return haystack_start;
}

解析:

只有前面有一个不相等,那么前缀就不相等,同时注意还需要往后推进,也就是++

答案为:*(haystack++)!=*(needle++)

第六题:三部排序

#include <stdio.h>
void sort3p(int *x,int len)
{ 
	int p=0;
	int left=0;
 	int right=len-1;
 	int t;
 	while(p<=right)
    { 
    	if(x[p]<0)
        { 
        	t=x[left];  x[left]=x[p];  x[p]=t;  left++;  p++; 
       	}
	  	else if(x[p]>0) 
	  	{ 
	  		t=x[right];  x[right]=x[p];  x[p]=t;  right--; 
	  	}
		else 
		{ 
			_______________________//填空位置
		}
	}
}

解析:

代码已经写得很清楚了:对p[x]分为以下三种情况

那么根据题意描述可知p相当于i,就是一个迭代的工具而已,所以要让p++,然后else的情况肯定是对应着0的,所以答案为:

x[p++]=0

第七题:错误票据

 

 解析:

因为题目说:断号不可能发生在最小值和最大值,因此就以它们两作为边界,用哈希表记录频数即可

#include<iostream>
#include<algorithm>
using namespace std;

const int N=1e5+10;
const int INF=0x3f3f3f3f;
int ha[N];

int main()
{
    int n;
    cin>>n;
    int minv=INF;
    int maxv=-INF;
    int tp;
    while(cin>>tp)
    {
        if(tp<minv) minv=tp;
        if(tp>maxv) maxv=tp;
        ha[tp]++;
    }
    int ans1=0,ans2=0;
    for(int i=minv;i<=maxv;i++)
    {
        if(ha[i]==0) ans1=i;
        if(ha[i]==2) ans2=i;
    }
    
    cout<<ans1<<" "<<ans2<<endl;
    
    return 0;
}


第八题:买不到的数目(打表找数学规律)

 打表:

#include<iostream>
using namespace std;
int n, m;

int main()
{
	cin >> n >> m;
	int k = n * m;

	while (k)
	{
		int t = k;
		while (t % m != 0 && t - n > 0) t -= n;
		//条件1 条件2 条件3
		if (t % m != 0 && k % n != 0 && k % m != 0)
		{
			cout << k << endl;
			break;
		}
		k--;
	}

	return 0;
}

正解:

#include<iostream>
using namespace std;
int n,m;
int main()
{
    cin>>n>>m;
    cout<<(n-1)*(m-1)-1<<endl;
    
    return 0;
}

第九题:剪格子(困难)

活动 - AcWing


第十题:大臣的旅费(树的直径+dfs)

 

 vector模拟链表:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;

const int N = 100010;
int n;
struct  Edge
{
	int id, w;//指向的那条边,和这条边的边长
};
vector<Edge> h[N];
int dist[N];

void dfs(int u, int father, int distance)
{
	dist[u] = distance;//记录长度

	for (auto node : h[u])//想象成单链表
	{
		if (node.id != father)//保证不会往回走,保证向下走
			dfs(node.id, u, distance + node.w);//当前节点,u则为当前节点的父亲,距离增加
	}
}

int main()
{
	scanf("%d", &n);
	for (int i = 0; i < n - 1; i++)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		h[a].push_back({ b,c });
		h[b].push_back({ a,c });
	}

	dfs(1, -1, 0);//第一次传参:当前节点,当前节点的父亲,当前节点到父节点的距离

	int u = 1;
	for(int i=1;i<=n;i++)
		if (dist[i] > dist[u])//寻找从1号点到最远能到的路径距离
		{
			u = i;
		}

	dfs(u, -1, 0);//上述的最远的能到的距离作为头,从新开始寻找离它的最远距离

	for(int i=1;i<=n;i++)
		if (dist[i] > dist[u])//同理
		{
			u = i;
		}

	int s = dist[u];//u到最远的距离

	printf("%lld\n", s * 10 + s * (s + 1ll) / 2);

	return 0;
}

数组模拟链表:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010, M = 200010;

int n;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

void dfs(int u, int father, int distance)
{
    dist[u] = distance;
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if (j != father)
            dfs(j, u, distance + w[i]);
    }
}

int main()
{
    scanf("%d", &n);
    memset(h, -1, sizeof h);

    for (int i = 0; i < n - 1; i ++ )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c), add(b, a, c);
    }

    dfs(1, -1, 0);

    int u = 1;
    for (int i = 2; i <= n; i ++ )
        if (dist[u] < dist[i])
            u = i;

    dfs(u, -1, 0);

    for (int i = 1; i <= n; i ++ )
        if (dist[u] < dist[i])
            u = i;

    printf("%lld\n", dist[u] * 10 + (dist[u] + 1ll) * dist[u] / 2);

    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/178927/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值