2016 蓝桥杯a组

某君新认识一网友。 当问及年龄时,他的网友说: “我的年龄是个2位数,我比儿子大27岁, 如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄” 
请你计算:网友的年龄一共有多少种可能情况? 
提示:30岁就是其中一种可能哦. 请填写表示可能情况的种数。 

注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

#include <cstdio>

using namespace std;

int main() {
    int ans=0;
    for(int i=1;i<=9;++i)
        for(int j=0;j<=9;++j)
            if(10*i+j-10*j-i==27)
                ++ans;
    printf("%d\n",ans);
}

生日蜡烛

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。

现在算起来,他一共吹熄了236根蜡烛。

请问,他从多少岁开始过生日party的?

请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。


题目的意思很明了,求那一岁开始生日

思路:直接枚举开始过生日的那一岁即可

#include <iostream>

using namespace std;

int main()
{
    for(int i=1;i<100;i++)
    {
        int sum=0;
        for(int j=i;j<100;j++)
        {
            sum+=j;
            if(sum>236)
                break;
            if(sum==236)
                cout<<i<<"->"<<j<<endl;
        }

    }
    return 0;
}

四则运算 (DFS)

有1~13共13个数,将12个不同的数填入下列12个空使四个运算都成立,问有多少种方法?


依旧是dfs+剪枝就能秒出,答案是:64,感觉当时写的不是64,估计当时拷代码时有地方没改 :(

[cpp]  view plain  copy
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int num[15] = {}, cnt = 0;


void dfs(int num[])
{
    if(num[1] + num[2] == num[3])
    {
        if(num[4] - num[5] == num[6])
        {
            if(num[7] * num[8] == num[9])
            {
                if(num[10] == num[11] * num[12])
                {
                    cnt++;
                }
            }
        }
    }
}
int main()
{
    for(int i = 1; i <= 13; i++)
    {
        num[i] = i;
    }
    do{
        dfs(num);
    }while(next_permutation(num + 1, num + 14));
    printf("%d\n", cnt);
    return 0;

}

第五题


消除尾一

下面的代码把一个整数的二进制表示的最右边的连续的1全部变成0
如果最后一位是0,则原数字保持不变。

如果采用代码中的测试数据,应该输出:
00000000000000000000000001100111   00000000000000000000000001100000
00000000000000000000000000001100   00000000000000000000000000001100

请仔细阅读程序,填写划线部分缺少的代码。


#include <stdio.h>

void f(int x)
{
    int i;
    for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
    printf("   ");
    
    x = _______________________;
    
    for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
    printf("\n");    
}

int main()
{
    f(103);
    f(12);
    return 0;
}


注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

这个题就是要将尾部的连续1变成0.

思路:怎么能将后面的1全部变成0能还要保持如果原来是连续0的不变?我们采用加一的操作,使得最后的连续一向前进了一位,但是后面全部变成了0.

00000000000000000000000001100111 如果加一应该变成00000000000000000000000001101000,连续1向高位进了一位。处理进位使用&位操作。&位运算指对应位都为1时为1.这样就能将向高位的1去掉变0.

答案:x=x&(x+1);



对比x原始值A1B,x&(x-1)即把最后一个1改成0.

位运算.&是位与的意思,只有当两边都为1时,才为1.
比如说x初始化为5,即其二进制表示为00000101,x-1=4,4的二进制表示为00000100,
x=x&(x-1)=5&4=101&100=100=4;

x&(x+1)是把后面连续1变为0

lowbit详解

#define lowbit(x) ((x)&(-x)) 

也可以写成如下形式:

int Lowbit(x) {

  return x&(-x);

}

例如:

1> x = 1:

十进制转二进制(设位数为8):

1 => 0000 0001

-1=> 1111 1111(此处为1的补码)

1&(-1)的二进制位运算为(二个二进位都为1):

所以1&(-1)=1

2> x = 6:

十进制转二进制(设位数为8):

6 => 0000 0110

-6=> 1111 1010(此处为6的补码)

6&(-6)的二进制位运算为(二个二进位都为1):


ps



这题当时我想了很久,因为它必须在一行内就算出来,所以我想到了lowbit,它可以很方便的得到。 
然而怎么让它套用上lowbit也不是一件容易的事。。。不过最后还是做出来了~

要消除x末尾所有的1,可以先把x加上1:

00000000000000000000000001100111 + 1 =
00000000000000000000000001101000
  • 1
  • 2

再减去新的数的lowbit:

00000000000000000000000001101000 - 00000000000000000000000000001000 =
00000000000000000000000001100000 
  • 1
  • 2

所以我的答案是:x+1-((x+1)&(-x-1)) 
当然标准答案更加简单:x&(x+1)


#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;

const int MAXN=5000005;
short power[MAXN]={0};

void Solve(int n)
{
    for(int i=0;i*i<=n;i++)
    {
        for(int j=0;j*j<=n;j++)
        {
            //如果下面的已经不能表示成两个数的平方和,跳过
            if(power[n-i*i-j*j]==0) continue;
            for(int k=0;k*k<=n;k++)
            {
                int temp=n-i*i-j*j-k*k;
                double x=sqrt((double)temp);
                if(x ==(int)x)
                {
                    cout<<i<<" "<<j<<" "<<k<<" "<<(int)x<<endl;
                    return;
                }
            }
        }
    }
}

int main()
{
    int n;
    //预处理
    for(int i=0;i*i<=n;i++)
        for(int j=0;j*j<=n;j++)
            if(i*i+j*j<=n)
                power[i*i+j*j]=1;
    cin>>n;
    Solve(n);
    return 0;
}


寒假作业

现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:

   □ + □ = □
   □ - □ = □
   □ × □ = □
   □ ÷ □ = □
   
   (如果显示不出来,可以参见【图1.jpg】)
   
每个方块代表1~13中的某一个数字,但不能重复。
比如:
 6  + 7 = 13
 9  - 8 = 1
 3  * 4 = 12
 10 / 2 = 5

以及: 
 7  + 6 = 13
 9  - 8 = 1
 3  * 4 = 12
 10 / 2 = 5

就算两种解法。(加法,乘法交换律后算不同的方案)
 
你一共找到了多少种方案?


请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:有的人的做法是将数全部填完以后再去判断,总共12个数,每个数有13种选择,如果全部填完复杂度还是蛮高的。我的方法是按照加减乘除的顺序进行判断,唯有满足上面的条件才认为通过。


#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int num[15] = {}, cnt = 0;


void dfs(int num[])
{
    if(num[1] + num[2] == num[3])
    {
        if(num[4] - num[5] == num[6])
        {
            if(num[7] * num[8] == num[9])
            {
                if(num[10] == num[11] * num[12])
                {
                    cnt++;
                }
            }
        }
    }
}
int main()
{
    for(int i = 1; i <= 13; i++)
    {
        num[i] = i;
    }
    do{
        dfs(num);
    }while(next_permutation(num + 1, num + 14));
    printf("%d\n", cnt);
    return 0;

}

9. 密码脱落
X星球的考古学家发现了一批古代留下来的密码。 
这些密码是由A、B、C、D 四种植物的种子串成的序列。 
仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串)。 
由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。


你的任务是: 给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。


输入一行,表示现在看到的密码串(长度不大于1000) 
要求输出一个正整数,表示至少脱落了多少个种子。


例如,输入: 
ABCBA 
则程序应该输出: 

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


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


请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。 
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 
注意: main函数需要返回0 
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。 注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。 

提交时,注意选择所期望的编译器类型。


回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。每个字符串都可以通过向中间添加一些字符,使之变为回文字符串。
例如:abbc 添加2个字符可以变为 acbbca,也可以添加3个变为 abbcbba。方案1只需要添加2个字符,是所有方案中添加字符数量最少的

求增添几个字符使得字符串为回文串。。解法:讲字符串翻转,求出与原串的最长公共子序列。。用字符串的长度减去其值 即为答案!!!

#include <bits/stdc++.h>
using namespace std;

char s[1010];
int dp[1010][1010];

int main()
{
    scanf("%s",s+1);
    int n=strlen(s+1);
    for (int i=1;i<=n;i++) {
        for (int j=1;j<=n;j++) {
            if (s[i]==s[n+1-j]) {
                dp[i][j]=dp[i-1][j-1]+1;
            } else {
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    printf("%d\n",n-dp[n][n]);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值