第五届蓝桥杯省赛个人赛

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

void dfs(int *a,int i,int sum)
{
   if(sum > 1)  return;
   if(i==n)
   {
      for(int j=1; j<=n; j++)
           cout<<"1/"<<a[j]<<" ";
      cout<<endl;
      return;
   }
   for(int k=a[i]+1;  k<=30; k++)
   {
      a[i+1]=k;
      sum+=k;
      dfs(a,i+1,sum);
      sum-=k;
   }
}

int main()
{
   cin>>n;
   int *a;
   a=new int[n+1];
   memset(a,0,sizeof(int));
   dfs(a,0,0);
}

A组

2.

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

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

参见【图1.png】

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

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

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

注意:只填写该小数本身,不要填写任何多余的说明或解释文字。

注:简单的for循环,注意使用实数类型。

#include<iostream>
using namespace std;

int main()
{
	float pai=0.0,i;
	int num=0;
	for(i=1.0; i<100; i++)
	{
		if(num%2)
			pai=pai-1.0/(2*i-1);
		else
			pai=pai+1.0/(2*i-1);
		num++;
	}	
	cout<<pai*4<<endl;
	return 0;
} 
3.
如果x的x次幂结果为10(参见【图1.png】),你能计算出x的近似值吗?

显然,这个值是介于2和3之间的一个数字。
请把x的值计算到小数后6位(四舍五入),并填写这个小数值。注意:只填写一个小数,不要写任何多余的符号或说明。

注:可以采用暴力方式,求 2 和 3 中间的数,循环求解。

#include<iostream>

#include<math.h>

using namespace std;

int main()

{

       double i=2;

       while(i<3)

      {

             if(fabs(i*i)-10<0.000001)

            {cout<<i<<endl;  return 0;}

            i=i+0.00000001;

      }
}


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

17126425374635

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

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

注意:只填写这个14位的整数,不能填写任何多余的内容,比如说明注释等。

注:采用深度优先搜索,寻找每个数的位置

#include<iostream>
using namespace std;
int a[15];

int dfs(int n)
{
	int i;
	if(n==4) n++;
	if(n>6) return 1;
	for(i=3; i<=14; i++)
	{
		if(i==7 || i==9) continue;
		if(a[i+n+1]==0 && a[i]==0 && i+n+1<=14)
		{
			a[i+n+1]=a[i]=n;
			if(dfs(n+1)) return 1;
			a[i+n+1]=a[i]=0;
		}	
	}	
	return 0;
} 

int main()
{
	a[1]=7;a[9]=7;
	a[2]=4;a[7]=4;
	dfs(1);
	for(int i=1; i<=14; i++)
		cout<<a[i];
	cout<<endl;
        return 0;
 }

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

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

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

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

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

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

再例如,输入:
3
程序应该输出:
0
资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms

#include<iostream>
using namespace std;

int main()
{
   int ans=0;
   double a,b,c;
   cin>>c;
   for(int a=1.0; a<=1.0*c/sqrt(2); a++)
   {
      b=sqrt(c*c-a*a);
      if(b==int(b))
         ans++;
   }
   cout<<ans<<endl;
   return 0;
}
6.


你一定听说过“数独”游戏。
如【图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

资源约定:
峰值内存消耗 < 256M
CPU消耗  < 2000ms

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
      
      
#define M 11       
    struct point  
    {  
        int x, y;  
    } p[100];  

    //row[i][j]表示第i行是否有数字j,col[i][j]表示第i列是否有数字j,mat[i][j][k]表示第(i,j)位置的小九宫格里是否有数字k  
    int Map[M][M];  
    bool flag, row[M][M], col[M][M], mat[3][3][M];  
    int np;  
         
    void DFS(int num)  
    {  
        if (flag) return;  
      
        int i, j;  
         
       if (num == -1)  
        {  
            for (i = 0; i < 9 && !flag; i++)  
            {  
                for (j = 0; j < 9; j++)  
                    printf ("%d", Map[i][j]);  
                printf ("\n");  
            }  
            flag = true;  
            return;  
        }  
      
      
        for (i = 1; i <= 9 && !flag; i++)  
        {  
            int x = p[num].x;  
            int y = p[num].y;  
            if (!row[x][i] && !col[y][i] && !mat[x/3][y/3][i])  
            {  
                row[x][i] = col[y][i] = mat[x/3][y/3][i] = true;  
                Map[x][y] = i;  
                DFS(num-1);  
                row[x][i] = col[y][i] = mat[x/3][y/3][i] = false;  
                Map[x][y] = 0;  
            }  
        }  
    }  
      
      
    int main()  
    {  
        int  i, j;  
      
            memset (row, false, sizeof (row));  
            memset (col, false, sizeof (col));  
            memset (mat, false, sizeof (mat));  
            np = 0;  
            for (i = 0; i < 9; i++)  
            {  
                for (j = 0; j < 9; j++)  
                {  
                    scanf ("%1d", &Map[i][j]);                      // 新技能  
                    int num = Map[i][j];  
                    if (num)  
                        row[i][num] = col[j][num] = mat[i/3][j/3][num] = true;  
                    else  
                    {  
                        p[np].x = i;  
                        p[np++].y = j;  
                    }  
                }  
            }  
            flag = false;  
            DFS(np-1);  
        return 0;  
    }  


7.


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

数据规模与约定
对于20%的数据,n ≤ 20;
对于40%的数据,n ≤ 100;
对于100%的数据,1 ≤ n ≤ 100000。


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 2000ms

 #include<iostream>
#include<cstring>
#include<cmath>
#include<conio.h>//???组合数 是什么
bool judge(long c[],long m);
int combine(long a[],long n,long m,long c[],const long M);
long a[100001];//储存士兵编号
long b[100001];//储存领导编号
long c[100001];//储存组合
long long count=0;
int main()
{
	long n,i;
	scanf("%d",&n);
	b[1]=0;//将军没有领导
	for(i=2; i<=n; i++)
		scanf("%d",&b[i]);//储存领导编号 
	for(i=1; i<=n; i++)
		a[i]=i;//给士兵编号 
	for(i=1; i<=n; i++)
		combine(a,n,i,c,i);//从n个人中调出i个人
	printf("%ld\n",count);
	return 0; 
} 

//组合数 
int combine(long a[],long n,long m,long c[],long M)
{
	for(long i=n; i>=m; i--)
	{
		c[m]=i;
		if(m>1)
			combine(a,i-1,m-1,c,M);
		else
		{
			if(judge(c,M)) count++;
			count%=10007;
		 } 
	}
}

bool judge(long c[],long m)//判断其中是否有上级 
{
	long i,j;
	for(i=1; i<=m; i++)
	{
		for(j=1; j<=m; j++)
		if(b[c[i]]==c[j]) return false;
	}
	return true;
 } 

B组

1.
输入一个字符串,求它包含多少个单词。单词间以一个或者多个空格分开。
第一个单词前,最后一个单词后也可能有0到多个空格。
比如:" abc    xyz" 包含两个单词,"ab   c   xyz    "  包含3个单词。

如下的程序解决了这个问题,请填写划线部分缺失的代码。

注意:只填写划线部分的代码,不要填写任何多余的内容。比如已经存在的小括号,注释或说明文字等。


int get_word_num(char* buf)
{
    int n = 0;   
    int tag = 1;
    char* p = buf;
    
    for(;*p!=0 && *p!=13 && *p!=10;p++){
        if(*p==' ' && tag==0) tag=1;
        if( _____________________ ) { n++; tag=0; }   //填空
    }
    
    return n;
}

int main()
{
    char buf[1000];
    fgets(buf,1000,stdin);
    
    printf("%d\n", get_word_num(buf));
    return 0;
}

(*p >= 'a'&& *p <= 'z')||(*p >= 'A' && *p <= 'Z') && tag==1

2.
1/1 + 1/2 + 1/3 + 1/4 + ... 在数学上称为调和级数。

它是发散的,也就是说,只要加上足够多的项,就可以得到任意大的数字。

但是,它发散的很慢:

前1项和达到 1.0
前4项和才超过 2.0
前83项的和才超过 5.0

那么,请你计算一下,要加多少项,才能使得和达到或超过 15.0 呢?

请填写这个整数。

注意:只需要填写一个整数,不要填写任何多余的内容。比如说明文字。
#include<iostream>
using namespace std;

int main()
{
   double i,sum=0.0;
   int num=0;
   for(i=1.0; ; i++)
   {
      if(sum > 15) break;
      sum+=1.0/i;
      num++;
   }
   cout<<num<<endl;
   return 0;

}

C组

1.
二项式的系数规律,我国数学家很早就发现了。

如【图1.png】,我国南宋数学家杨辉1261年所著的《详解九章算法》一书里就出现了。

其排列规律:
1
1    1
1    2    1
1    3    3    1
1    4    6    4    1
1    5    10   10   5    1
1    6    15   20   15   6    1
1    7    21   35   35   21   7    1

如下的程序,用来建立N行的杨辉三角形。请填写划线部分缺少的代码。

注意:只填写划线部分的代码,不要填写任何多余的内容。


#define N 8
int main()
{
    int a[N][N];
    int i,j;
    
    for(i=0; i<N; i++){
        a[i][0] = 1;
        a[i][i] = 1;
    }
    
    for(i=1; i<N; i++){
        for(j=1; j<i; j++) ___________________________;
    }
    
    for(i=0; i<N; i++){
        for(j=0; j<=i; j++)    printf("%-5d", a[i][j]);
        printf("\n");
    }
    
    return 0;
}


a[i][j]=a[i-1][j]+a[i-1][j-1];
3.
有如下的加法算式。其中每个汉字代表一个数字。
(如果存在对齐问题,可参见【图1.png】)

                       年
                    大年
                 过大年
              能过大年
           怎能过大年
        我怎能过大年
+  让我怎能过大年
 ------------------
     能能能能能能能

请填写“让我怎能过大年” 所代表的整数。
所有数字连在一起,中间不要空格。例如:"3125697"。当然,这个不是正确的答案。
注意:只填写一个整数,不要填写任何多余的内容。


注:没有空间和时间的限制,采用暴力

#include<iostream>
using namespace std;

int main()
{
   int a,b,c,d,e,f,g;
   for(a=1; a<10; a++)
    for(b=1; b<10; b++)
      for(c=1; c<10; c++)
        for(d=1; d<10; d++)
           for(e=1; e<10; e++)
             for(f=1; f<10; f++)
               for(g=1; g<10; g++)
               {
                   if(7*g%10==d  && (6*f+7*g/10)%10==d && (5*e+(6*f+7*g/10)/10)%10==d && (4*d+(5*e+(6*f+7*g/10)/10)/10)%10==d
                     &&  (3*c+(4*d+(5*e+(6*f+7*g/10)/10))%10==d && (2*b+(3*c+(4*d+(5*e+(6*f+7*g/10)/10))/10))%10==d
                     &&  (a+(2*b+(3*c+(4*d+(5*e+(6*f+7*g/10)/10))/10))/10)%10==d)
                    cout<<a<<b<<c<<d<<e<<f<<g<<endl;
                    return 0;                    
               }
 }
4.
1193是个素数,对它循环移位后发现:
1931,9311,3119也都是素数,这样特征的数叫:循环素数。

你能找出具有这样特征的5位数的循环素数吗?

当然,这样的数字可能有很多,请写出其中最大的一个。

注意:答案是个5位数,不要填写任何多余的内容。

注:判断素数和循环操作

#include<iostream>
#include<math.h>
using namespace std;

int make(int n)
{
   int k=sqrt(n);
   for(int i=2; i<=k; i++)
     if(n%i==0)  return 0;
   return 1;
}

int check(int i)
{
   int num=i;
   for(int j=0; j<5; j++)
   {
       if(!check(num))  return 0;
       num=num%10000*100000+num/10000;
   }
   return 1;
}

int main()
{
 int Max=100000;
 for(int i=100000; i<=99999; i++)
 if(check(i))  Max=max(Max,i);
 cout<<Max<<endl;
 return 0;
 }
5.
把一个整数的每个数位都平方后求和,又得到一个整数,我们称这个整数为:位平方和。

对新得到的整数仍然可以继续这一运算过程。

比如,给定整数为4,则一系列的运算结果为:

16,37,58,89,....

本题的要求是,已知一个整数x,求第n步的运算结果。

数据格式要求:

输入,两个整数x n,中间以空格分开。表示求x的第n步位平方和。其中,x,n都大于0,且小于100000。
输出,一个整数,表示所求结果。

例如,
输入:
4 3
则程序应该输出:
58

再例如,
输入:
1314 10
则程序应该输出:
20

资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms


#include<iostream>
using namespace std;

int pow(int i)
{
   return i*i;
}


int make(int i)
{
   int sum=0;
   while(i)
   {
       int r=i%10;
       sum+=pow(r);
       i/=10;
   }
   return sum;
 }

 int main()
{
    int num,n;
    cin>>num>>n;
    for(int i=0; i<n; i++)
       num=make(num);
    cout<<num<<endl;
    return 0;
 }
6.
形如:1/a 的分数称为单位分数。

可以把1分解为若干个互不相同的单位分数之和。
例如:
1 = 1/2 + 1/3 + 1/9 + 1/18
1 = 1/2 + 1/3 + 1/10 + 1/15
1 = 1/3 + 1/5 + 1/7 + 1/9 + 1/11 + 1/15 + 1/35 + 1/45 + 1/231
等等,类似这样的分解无穷无尽。

我们增加一个约束条件:最大的分母必须不超过30

请你求出分解为n项时的所有不同分解法。

数据格式要求:

输入一个整数n,表示要分解为n项(n<12)
输出分解后的单位分数项,中间用一个空格分开。
每种分解法占用一行,行间的顺序按照分母从小到大排序。

例如,
输入:
4
程序应该输出:
1/2 1/3 1/8 1/24
1/2 1/3 1/9 1/18
1/2 1/3 1/10 1/15
1/2 1/4 1/5 1/20
1/2 1/4 1/6 1/12

再例如,
输入:
5
程序应该输出:
1/2 1/3 1/12 1/21 1/28
1/2 1/4 1/6 1/21 1/28
1/2 1/4 1/7 1/14 1/28
1/2 1/4 1/8 1/12 1/24
1/2 1/4 1/9 1/12 1/18
1/2 1/4 1/10 1/12 1/15
1/2 1/5 1/6 1/12 1/20
1/3 1/4 1/5 1/6 1/20


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 2000ms

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

void dfs(int *a,int i,int sum)
{
   if(sum > 1)  return;
   if(i==n)
   {
      for(int j=1; j<=n; j++)
           cout<<"1/"<<a[j]<<" ";
      cout<<endl;
      return;
   }
   for(int k=a[i]+1;  k<=30; k++)
   {
      a[i+1]=k;
      sum+=k;
      dfs(a,i+1,sum);
      sum-=k;
   }
}

int main()
{
   cin>>n;
   int *a;
   a=new int[n+1];
   memset(a,0,sizeof(int));
   dfs(a,0,0);
}


















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值