第五届蓝桥杯

第一题:

一个串的子串是指该串的一个连续的局部。如果不要求连续,则可称为它的子序列。
比如对串: “abcdefg” 而言,“ab”,“abd”,“bdef” 等都是它的子序列。
特别地,一个串本身,以及空串也是它的子序列。

对两个串而言,可以有许多的共同的子序列,我们关心的是:它们所共同拥有的长度最大的子序列是多长。以下代码实现了这个问题的求解。请填写划线部分缺失的代码。

注意:只填写划线部分缺少的内容,不要填写任何多余的符号或注释、说明等。例如,不要填写已经给出的小括号。

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

const int N = 1e5 + 10;
int max(int a, int b)
{
    
    
	return a>b?a:b;
}

int f(char* x, char* y)
{
    
    
	if(strlen(x)==0) return 0;
	if(strlen(y)==0) return 0;
	
	if(*x == *y) return f(x+1, y+1) + 1;
	
	return max(_______________________);
	//f(x + 1, y), f(x, y + 1)
}

int main()
{
    
    
	printf("%d\n", f("ac","abcd")); //2
	printf("%d\n", f("acebbcde1133","xya33bc11de")); //5
	return 0;
} 

第二题:

历史上有许多计算圆周率pai的公式,其中,格雷戈里和莱布尼茨发现了下面的公式:

pai = 4*(1-1/3+1/5-1/7 …)

参见【图1.png】

这个公式简单而优美,但美中不足,它收敛的太慢了。
如果我们四舍五入保留它的两位小数,那么:

累积了1项和是:4.00
累积了2项和是:2.67
累积了3项和是:3.47
。。。

请你写出它累积了100项的和是多少(四舍五入到小数后两位)。

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

const int N = 1e5 + 10;

int main()
{
    
    
    double pi = 1;
    int sign = -1;
    int cnt = 1;
    for(int i = 3; i <= 199; i += 2)
    {
    
    
        if(cnt % 2)
            pi += sign * (double)1.0 / i;
        else
            pi += (double)1.0 / i;
        cnt ++ ;
    }
    
    printf("%.2lf\n", pi * 4);//3.13
    return 0;
}

第三题:

如果x的x次幂结果为10(参见【图1.png】),你能计算出x的近似值吗?

显然,这个值是介于2和3之间的一个数字。

请把x的值计算到小数后6位(四舍五入),并填写这个小数值。

注意:只填写一个小数,不要写任何多余的符号或说明。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

int main()
{
    
    
	double x = 2.0;
	while(x < 3.0)
	{
    
    
		x = x + 0.00000001;
		if(fabs(pow(x, x) - 10.0) < 0.000001)
		{
    
    
			printf("%.8lf\n", x);
		}
	}
	return 0;
}

第四题:

今有7对数字:两个1,两个2,两个3,…两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:

17126425374635

当然,如果把它倒过来,也是符合要求的。

请你找出另一种符合要求的排列法,并且这个排列法是以74开头的。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

const int N = 1e5 + 10;

int a[] = {
    
    0, 7, 4, 0, 0, 0, 0, 4, 0, 7, 0, 0, 0, 0, 0};

void dfs(int n)
{
    
    
    if(n == 4) dfs(n + 1);
    if(n == 7)
    {
    
    
        for(int i = 1; i <= 14; i ++ ) printf("%d", a[i]);
        puts("");
    }
    
    for(int i = 3; i <= 14; i ++ )
    {
    
    
        if(i == 7 || i == 9) continue;
        int p = n + i + 1;
        if(p > 14) continue;
        if(a[i] == 0 && a[p] == 0)
        {
    
    
            a[i] = n, a[p] = n;
            dfs(n + 1);
            a[i] = 0, a[p] = 0;
        }
    }
}

int main()
{
    
    
	dfs(1);
	
	return 0;
}

第五题:

勾股定理,西方称为毕达哥拉斯定理,它所对应的三角形现在称为:直角三角形。

已知直角三角形的斜边是某个整数,并且要求另外两条边也必须是整数。

求满足这个条件的不同直角三角形的个数。

【数据格式】
输入一个整数 n (0<n<10000000) 表示直角三角形斜边的长度。
要求输出一个整数,表示满足条件的直角三角形个数。

例如,输入:
5
程序应该输出:
1

再例如,输入:
100
程序应该输出:
2

再例如,输入:
3
程序应该输出:
0

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

int main()
{
    
    
	int n;
	scanf("%d", &n);
	int res = 0;
	for(int i = 3; i < n; i ++ )
	{
    
    
	    int a = (int)sqrt(n * n - i * i);
	    if(a * a + i * i == n * n) res ++ ;
	}
	printf("%d\n", res / 2);
	return 0;
}

第六题:

你一定听说过“数独”游戏。
如【图1.png】,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。

数独的答案都是唯一的,所以,多个解也称为无解。

本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。

本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。

格式要求:
输入9行,每行9个数字,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。

例如:
输入(即图中题目):
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700

程序应该输出:
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764

再例如,输入:
800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400

程序应该输出:
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452

#include <iostream>
#include <cstring>

using namespace std;

const int N = 9, M = 1 << N;
int row[N], col[N], cell[N][N];
int ones[M], map[M];
char str[100][100];

void init()
{
    
    
    for(int i = 0; i < N; i ++ )
        row[i] = col[i] = (1 << N) - 1;
        
    for(int i = 0; i < 3; i ++ )
        for(int j = 0; j < 3; j ++ )
            cell[i][j] = (1 << N) - 1;
}

void draw(int x, int y, int t, bool is_set)
{
    
    
    if(is_set) str[x][y] = t + '1';
    else str[x][y] = '0';
    
    int v = 1 << t;
    if(!is_set) v = -v;
    
    row[x] -= v;
    col[y] -= v;
    cell[x / 3][y / 3] -= v;
}

int lowbit(int x)
{
    
    
    return x & -x;
}

int get(int x, int y)
{
    
    
    return row[x] & col[y] & cell[x / 3][y / 3];
}

bool dfs(int cnt)
{
    
    
    if(!cnt) return true;
    
    int minv = 10;
    int x, y;
    for(int i = 0 ; i < N; i ++ )   
        for(int j = 0; j < N; j ++ )
        {
    
    
            if(str[i][j] == '0')
            {
    
    
                int state = get(i, j);
                if(ones[state] < minv)
                {
    
    
                    minv = ones[state];
                    x = i, y = j;
                }
            }
        }
        
    int state = get(x, y);
    for(int i = state; i; i -= lowbit(i))
    {
    
    
        int t = map[lowbit(i)];
        draw(x, y, t, true);
        if(dfs(cnt - 1)) return true;
        draw(x, y, t, false);
    }
    return false;
}

int main()
{
    
    
    int n = 9;
    int m = 9;
    for(int i = 0; i < N; i ++ ) map[1 << i] = i;
    for(int i = 0; i < 1 << N; i ++ )
        for(int j = 0; j < N; j ++ )
            ones[i] += (i >> j & 1);
    init();
    for(int i = 0; i < n; i ++ )
        scanf("%s", str[i]);
        
        
        
        int cnt = 0;
        for(int i = 0; i < N; i ++ )
            for(int j = 0; j < N; j ++ )
                if(str[i][j] != '0')
                {
    
    
                    int t = str[i][j] - '1';
                    draw(i, j, t, true);
                }
                else cnt ++ ;
        
        dfs(cnt);
        
        for(int i = 0; i < n; i ++ )
        {
    
    
            printf("%s", str[i]);
                puts("");
        }
    
    return 0;
}

第七题:

G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。
请问,G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。
输入格式
输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。
接下来n-1个数,分别表示编号为2, 3, …, n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。
输出格式
输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。
样例输入1
3
1 1
样例输出1
4
样例说明
这四种方式分别是:

  1. 选1;
  2. 选2;
  3. 选3;
  4. 选2, 3。
    样例输入2
    7
    1 1 2 2 3 3
    样例输出2
    40

解析:
把父节点和子节点分开就可以很好地计算,利用递归即可

#include<stdio.h>
#include<string.h>
int a[100001],b[100001];
int n,t;
int str(int i)
{
    
        
    if(i>n)                //假如已经将n名士兵遍历一遍,就加一
    {
    
    
        t++;
        return t;    
    }
    if(a[b[i]]==0)                //假如第i名士兵的直接上级已经出列
    {
    
    
        str(i+1);                 //那么这名士兵就不能出列,直接跳到下一位
    }
    else                    //假如第i名士兵的直接上级没有出列
    {
    
    
        a[i]=0;                //让他出列并跳到下一位
        str(i+1);
        a[i]=i;                //不让他出列并跳到下一位
        str(i+1);
    }
}
int main()
{
    
    
    int i,j;
    while(scanf("%d",&n)!=EOF)
    {
    
    
        t=0;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        a[0]=1;
        for(i=1;i<=n;i++)
        {
    
    
            a[i]=i;                    //储存当前状态,如果已经出列就置为0
        }
        
        b[1]=0;                        
        for(i=2;i<=n;i++)
        {
    
    
            scanf("%d",&b[i]);        //记录第i号士兵的直接上级
        }
        
        printf("%d\n",(str(1)-1)%10007);        //因为要排除没有人去的情况,所以要减一
    }
    
    return 0;
 }

猜你喜欢

转载自blog.csdn.net/qq_45772236/article/details/108834946