请你计算:网友的年龄一共有多少种可能情况?
提示: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,估计当时拷代码时有地方没改 :(
#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
则程序应该输出:
0
再例如,输入:
ABECDCBABC
则程序应该输出:
3
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。 注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
求增添几个字符使得字符串为回文串。。解法:讲字符串翻转,求出与原串的最长公共子序列。。用字符串的长度减去其值 即为答案!!!
#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;
}