蓝桥杯小练

文章目录

    • 暴力枚举
      • A.日期问题
    • 递归
      • A.李白打酒
      • B.移动字母
    • 全排列(next_permutation())
      • A.六角填数
      • B.算式900
      • C.排它平方数
    • 常用函数
    • 注意!


暴力枚举

A.日期问题

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在 1960 年 1 月 1 日至 2059 年 12 月 31 日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如 02/03/04,可能是 2002 年 03 月 04 日、2004 年 02 月 03 日或 2004 年 03 月 02 日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
输入描述
一个日期,格式是 “AA/BB/CCAA/BB/CC” (0≤A,B,C≤9)。
输出描述
输出若干个不相同的日期,每个日期一行,格式是 “yyyy-MM-ddyyyy−MM−dd”。多个日期按从早到晚排列。

#include
using namespace std;

int mon[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int year,int month,int day)
{
    if(month<=0||month>12)
        return false;
    if(month!=2)
    {
        if(day<=0||day>mon[month])
            return false;
    }
    else
    {
        int leap=((year%4==0&&year%100!=0)||year%400==0);
        if(day<=0||day>mon[month]+leap)
            return false;
    }
    return true;
}
int main()
{
     int a,b,c;
     scanf("%d/%d/%d",&a,&b,&c);
     for(int i=19600101;i<=20591231;i++)
     {
         int year=i/10000,month=i/100%100,day=i%100;
         if(check(year,month,day))
         {
             if((year%100==a&&month==b&&day==c)//年月日
                ||(year%100==c&&month==a&&day==b)//月日年
                ||(year%100==c&&month==b&&day==a)//日月年
                )
            printf("%d-%02d-%02d\n",year,month,day);
         }
     }
    return 0;
}

一开始想根据给定数字拓展为日期,发现直接遍历每一个数字后筛选出符合日期的数字并且后两位与给定数字对比判断即可。


递归

A.李白打酒

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
话说大诗人李白,一生好饮。幸好他从不开车
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。 逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花 10次,已知最后一次遇到的是花,他正好把酒喝光了。请你计算出所有可能方案的个数(包含题目给出的)。

#include
int sum= 0;
void f(int dian, int hua, int jiu)
{
    if (dian == 0 && hua == 0 && jiu == 1)
    {
    	sum++;
    	return ;
    }
    if (dian > 0)
       f(dian - 1, hua, jiu * 2);
    if (hua > 0)
        f(dian, hua - 1, jiu - 1);
}
int main()
{
   f(5, 9, 2);
   cout<<sum;
    return 0;
}

#include 
using namespace std;
int sum=0;

void f(int dian,int hua,int jiu)
{
  if(dian==5&&hua==9&&jiu==1)
  {
    sum++;
    return ;
  }
  if(dian<5) f(dian+1,hua,jiu*2);
  if(hua<9) f(dian,hua+1,jiu-1);
}

int main()
{
  f(0,0,2);
  cout<<sum;
  return 0;
}

B.移动字母

2x3=6 个方格中放入 ABCDE 五个字母,右下角的那个格空着。如下图所示。
蓝桥杯小练_第1张图片
和空格子相邻的格子中的字母可以移动到空格中,比如,图中的 C 和 E 就可以移动,移动后的局面分别是:
A B
D E C
A B C
D E
为了表示方便,我们把 6 个格子中字母配置用一个串表示出来,比如上边的两种局面分别表示为:
ABDEC
ABCD
E
题目的要求是:请编写程序,由用户输入若干表示局面的串,程序通过计算,输出是否能通过对初始状态经过若干次移动到达该状态。可以实现输出 1,否则输出 0。初始状态为:ABCDE*。
输入描述
先是一个整数 n,表示接下来有 n行状态。
输出描述
程序输出 n 行 1 或 0。

#include
#include
using namespace std;

const string s = "ABCDE*";
string str;
int sum = 0;

void trace(int t)
{
    if(str == s && t < 6)
    {
        sum++;
        return;
    }
    for(int i = 0; i<4; i++)
    {
        int s;
        if(i == 0)
            s = t - 1;
        else if(i == 1)
            s = t - 3;
        else if(i == 2)
            s = t + 1;
        else if(i == 3)
            s = t + 3;
        if(s >= 0 && s <= 5)
        {
            swap(str[s], str[t]);
            trace(t+1);
            swap(str[s], str[t]);
        }
    }
}

int main()
{
    int n;
    cin >> n;
    getchar();
    while(n--)
	{
        getline(cin, str);
        trace(0);
        if(sum > 0)
            cout << "1" << endl;
        else cout << "0" << endl;
        sum = 0;
    }
     return 0;
}


全排列(next_permutation())

适合必须每个元素都不同的问题,可以避免暴力便利,思想也简单很多。

A.六角填数

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
如下图所示六角形中,填入 1 ~ 12 的数字。使得每条直线上的数字之和都相同。

蓝桥杯小练_第2张图片

#include 
#include
using namespace std;
int main()
{
  int arr[]={2,4,5,6,7,9,10,11,12};
  do{
      int a1=8+arr[0]+arr[1]+arr[2];
      int a2=8+arr[3]+arr[6]+3;
      int a3=1+arr[0]+arr[3]+arr[5];
      int a4=1+arr[1]+arr[4]+arr[8];
      int a5=3+arr[2]+arr[4]+arr[7];
      int a6=arr[5]+arr[6]+arr[7]+arr[8];
      if(a1==a2&&a1==a3&&a1==a4&&a1==a5&&a1==a6){
        cout<<arr[3]<<endl;
        return 0;
      }
  }while(next_permutation(arr,arr+9));
  return 0;
}

B.算式900

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
小明的作业本上有道思考题:看下面的算式:
(□□□□-□□□□)*□□=900
其中的小方块代表 0 ~ 9 的数字,这 10 个方块刚好包含了 0 ~ 9 中的所有数字。 注意:0 不能作为某个数字的首位。
小明经过几天的努力,终于做出了答案!如下:(5012-4987)*36=900
用计算机搜索后,发现还有另外一个解,本题的任务就是:请你算出这另外的一个解。
注意:输出格式需要与示例严格一致; 括号及运算符号不要用中文输入法; 整个算式中不能包含空格。

#include 
using namespace std;
int main()
{
  int a[10]={0,1,2,3,4,5,6,7,8,9};
  do
  {
  	int n=a[0]*1000+a[1]*100+a[2]*10+a[3];
  	int b=a[4]*1000+a[5]*100+a[6]*10+a[7];
  	int c=a[8]*10+a[9];
  	if((n-b)*c==900&&n!=5012&&a[0]!=0&&a[4]!=0&&a[8]!=0)
  	printf("(%d-%d)*%d=900",n,b,c);
  }while(next_permutation(a,a+10));
  return 0;
}

C.排它平方数

题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
小明正看着 203879203879 这个数字发呆。
原来,203879 * 203879 = 41566646641
这有什么神奇呢?仔细观察,203879203879 是个 66 位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。
具有这样特点的 6 位数还有一个,请你找出它!
再归纳一下筛选要求:
6 位正整数;
每个数位上的数字不同;
其平方数的每个数位不含原数字的任何组成数位。

#include 
using namespace std;

int a[10]={0,1,2,3,4,5,6,7,8,9};
int main(){
    long long sum1,sum2,x,s;
    while(next_permutation(a,a+10)){
        if(a[0]!=0){
            sum1=a[0]*100000+a[1]*10000+a[2]*1000+a[3]*100+a[4]*10+a[5];
            sum2=sum1*sum1;
            while(sum2){
                x=0;
                if(sum2%10==a[0]||sum2%10==a[1]||sum2%10==a[2]||sum2%10==a[3]||sum2%10==a[4]||sum2%10==a[5]){
                    x=1;
                    break;
                }
                sum2/=10;
            }
            if(x==0&&sum1!=203879) s=sum1;
        }
    }
    cout<<s<<endl;
    return 0;
}

常用函数

判断闰年

int check(int x)
{
  if(x%400==0||x%4==0&&x%100!=0)
  return 1;
  else return 0;
}

判断素数

int prim(int x)
{
	for(int i=2;i<sqrt(x);i++)
	{
		if(x%i==0)
		return 0;
	}
	return 1;
}

最大公约数

int gcd(int a,int b)
{
	if(b==0) return a;
	else return gcd(b,a%b);
}

最小公倍数

int d=gcd(a,b);
int lcm(int a,int b)
{
	return a/d*b;
}

进制转换

//p进制换10进制
int result=0,pro=1;
while(x)
{
	result=result+(x%10)*pro;
	x=x/10;
	pro=pro*p;
}
//10进制换q进制
int z[40],num=0;
do
{
	z[num++]=y%q;
	y=y/q;
}while(y);

注意!

  1. 整数相除却要输出小数时,记得x1.0。
  2. 有格式的输入输出用scanf和printf。输出补零: printf("%d-%02d-%02d\n",year,month,day);

你可能感兴趣的:(蓝桥杯)