注:本系列题目全是按照通过率降序来排列的,基本保证题目难度递增。
1、
题目名称:游戏任务标记
来源:腾讯
题目描述
游戏里面有很多各式各样的任务,其中有一种任务玩家只能做一次,这类任务一共有1024个,任务ID范围[1,1024]。请用32个unsigned int类型来记录着1024个任务是否已经完成。初始状态都是未完成。 输入两个参数,都是任务ID,需要设置第一个ID的任务为已经完成;并检查第二个ID的任务是否已经完成。 输出一个参数,如果第二个ID的任务已经完成输出1,如果未完成输出0。如果第一或第二个ID不在[1,1024]范围,则输出-1。
输入描述:
输入包括一行,两个整数表示人物ID.
输出描述:
输出是否完成
示例1
输入
1024 1024
输出
1
分析:经过(艰难的)读题,分析出只有两个数相等,才输出1,否则第二个ID一定未完成,输出0,不在范围输出-1即可。
p=(input().split())
f,s=int(p[0]),int(p[1])
if f not in range(1,1025) or s not in range(1,1025):print(-1)
elif s==f:print(1)
else:print(0)
当然,这可能不是题目的本意,真的这么写可能会被打。
1024=32*32,因此可用32个整数表示1024位(因为每个整数32位)
因为任务ID范围是1~1024,所以减1转化为0~1023
然后任务ID除以32,商为存到哪个整数,余数为该整数对应位(置1即可)
注:除以32相当于直接右移5位,对32取余相当于"与31"(这个技巧只对2的次方数有效).
#include <iostream>
using namespace std;unsigned int arr[32];int main()
{int id1, id2;while(cin>>id1>>id2){if(!(id2>=1 && id2<=1024)){cout<<-1<<endl;continue;}arr[(id1-1)>>5] |= (1<<(id1&31));cout<<( (arr[(id2-1)>>5] & (1<<(id2&31))) != 0)<<endl;}return 0;
}
2、
题目名称:网络走法数目
来源:美团
题目描述
有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回小团的走法数目。
输入描述:
输入包括一行,逗号隔开的两个正整数x和y,取值范围[1,10]。
输出描述:
输出包括一行,为走法的数目。
示例1
输入
3 2
输出
10
分析:
函数f(a,b)代表走到坐标(a,b)的走法数目
#include<iostream>
using namespace std;
int step(int m,int n){if(m == 0 || n == 0)return 1;return step(m - 1,n) + step(m,n -1);
}
int main(){int x,y;cin >> x >> y;cout << step(x,y) <<endl;
}
最笨写法,太多的重复子问题计算
简单动态规划
用二维表记录下来结果,并加以利用。
压缩:我们发现,除了这个位置上本身的数,DP[i,j]只和DP表中左边和上边的值有关,所以可以生成长度为矩阵较小边长一维表,用两层循环。注意顺序,从左向右打表,只有这样,左边的那个元素才是被更新过的,才是本行的左边那个元素。
l=(input().split())
x,y=int(l[0])+1,int(l[1])+1
l=[0]*x
l[0]=1
for p in range(y):for i in range(1,x):l[i]+=l[i-1]
print(l[-1])
3、
题目名称:幸运数
来源:京东
题目描述
小明同学学习了不同的进制之后,拿起了一些数字做起了游戏。小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中,二进制数也很常用。现在对于一个数字x,小明同学定义出了两个函数f(x)和g(x)。 f(x)表示把x这个数用十进制写出后各个数位上的数字之和。如f(123)=1+2+3=6。 g(x)表示把x这个数用二进制写出后各个数位上的数字之和。如123的二进制表示为1111011,那么,g(123)=1+1+1+1+0+1+1=6。 小明同学发现对于一些正整数x满足f(x)=g(x),他把这种数称为幸运数,现在他想知道,大于0且小于等于n的幸运数有多少个?
输入描述:
每组数据输入一个数n(n<=100000)
输出描述:
每组数据输出一行,小于等于n的幸运数个数。
示例1
输入
21
输出
3
分析:思想确实不难,按照题目意思走就可以了。实现稍微考察了coding能力吧,就要多练。
给出各种语言的实现:
python:
def f1(n):ret,t=0,nwhile 1:ret+= t%2t=t//2if t==0:breakreturn ret
def f2(n):q=0for i in str(n):q+=int(i)return q
r=int(input())
k=0
for i in range(1,r+1):if f1(i)==f2(i):k+=1
print(k)
java:
package 幸运数;
import java.util.*;
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNext()) {int n = in.nextInt();int count = 0;for (int i = 1; i <= n; i++) {if (f(i) == g(i)) {count++;}}System.out.println(count);}}/** 二进制 */private static int g(int n) {int sum = 0;while (n != 0) {sum += n % 2;n /= 2;}return sum;}/** 十进制 */private static int f(int n) {int sum = 0;while (n != 0) {sum += n % 10;n /= 10;}return sum;}
}
c++:
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<stdlib.h>
#define N 30;
using namespace std;
int f(int i)
{int sum = 0;while(i){sum+=i%10;i/=10;}return sum;
}
int g(int i)
{int sum = 0;for(int j = 1;j<100000;j*=2){if((j&i)==j) sum++;}return sum;
}
int main()
{//cout<<f(123)<<endl;cout<<g(123)<<endl;int n;while(cin>>n){int sum = 0;for(int i = 1;i<=n;i++){if(f(i)==g(i)) {sum++;}}cout<<sum<<endl;}return 0;
}
4、
题目名称:解救小易
来源:网易
题目描述
有一片1000*1000的草地,小易初始站在(1,1)(最左上角的位置)。小易在每一秒会横向或者纵向移动到相邻的草地上吃草(小易不会走出边界)。大反派超超想去捕捉可爱的小易,他手里有n个陷阱。第i个陷阱被安置在横坐标为xi ,纵坐标为yi 的位置上,小易一旦走入一个陷阱,将会被超超捕捉。你为了去解救小易,需要知道小易最少多少秒可能会走入一个陷阱,从而提前解救小易。
输入描述:
第一行为一个整数n(n ≤ 1000),表示超超一共拥有n个陷阱。
第二行有n个整数xi,表示第i个陷阱的横坐标
第三行有n个整数yi,表示第i个陷阱的纵坐标
保证坐标都在草地范围内。
输出描述:
输出一个整数,表示小易最少可能多少秒就落入超超的陷阱
示例1
输入
3
4 6 8
1 2 1
输出
3
分析:从[1,1]走到[X,Y]需要(X-1)+(Y-1)步这样对每个陷阱计算一下从[1,1]到陷阱所用的步数,求最小值即可。
n=int(input())
//保存横纵坐标
x=[int(x) for x in input().split()]
y=[int(x) for x in input().split()]
s=x[0]-y[0]-2//保存值
for i in range(n):s=min(x[i]+y[i]-2,s)
print(s)
5、
题目名称:身份证分组
来源:去哪网
题目描述
18位身份证的编码规则是:
前1、2位数字表示:所在省(直辖市、自治区)的代码
第3、4位数字表示:所在地级市(自治州)的代码
第5、6位数字表示:所在区(县、自治县、县级市)的代码;
第7—14位数字表示:出生年、月、日;
第15、16位数字表示:所在地的派出所的代码;
第17位数字表示性别:奇数表示男性,偶数表示女性;
第18位数字是校检码,用来检验身份证的正确性。
用户在输入身份证的过程中经常会输入错误,为了方便用户正确输入需要在输入过程中对用户的输入按照 6+8+4 的格式进行分组,实现一个方法接收输入过程中的身份证号,返回分组后的字符
输入描述:
输入数据有多行,每一行是一个输入过程中的身份证号
输出描述:
分组后的字符串
示例1
输入
5021
502104 198803
5021041988033084
502104198803308324
输出
5021
502104 198803
502104 19880330 84
502104 19880330 8324
分析:就是判断一下字符串长度的情况
s=input().replace(' ','')
if len(s)<=6:print(s)
elif len(s)<=14:print(s[0:6]+' '+s[6:])
else:print(s[0:6]+' '+s[6:14]+' '+s[14:])
有些同学没学python,找了个别人的c++,自己看吧
#include <iostream>
#include <string>
using namespace std;//按顺序输出字符串,跳过空格
//重新确定空格的位置,输出时对非空格字符计数,6及18时输出一个空格
//注意一种特殊清空,字符串就6个,那么计数为6时不加空格
int main(){string s;while(getline(cin,s)){int cnt=0;for(int i=0;i<s.size();++i){if(s[i]!=' '){++cnt;cout<<s[i];if(i==s.size()-1) break;if(cnt==6||cnt==14) cout<<" ";}}cout<<endl;}
}