A 、 二进制数字翻转
Time Limit: 1000 ms
Memory Limit: 256 mb
输入数据组数t
每组数据输入一个十进制数x(0<x<2^32),将其二进制位反转(共32位),然后输出对应的十进制数
输入样例#:
2
2
3
输出样例#:
1073741824
3221225472
提示
2^32-1超出了int的范围,请使用long long
题目来源
北京邮电大学2018年机试题
真题链接在此
思路:模拟即可,先依次将十进制数字转化为二进制数字,然后在转化的时候,也随之进行新数字的生成,比如说4转为2进制只有在进行两次除以2的操作才能等于1,但这时候新的十进制要加上2的(32-2)次幂。而且只有当前对2取余等于1的时候才对新的十进制数字进行操作。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int main(){
int n;
cin>>n;
long long int m;
for(int i=1;i<=n;i++){
cin>>m;
long long int h=0;
int k=0;
while(m>0){
int mr=m%2; //若当前的取余的值等于1,那么要进行新数字的下一步操作。
if(mr==1){
long long int h2=1;
for(int j=1;j<32-k;j++){
h2=h2*2;
}
h+=h2;
}
m/=2;
k++;
}
cout<<h<<endl;
}
return 0;
}
B 、 数字填充
Time Limit: 1000 ms
Memory Limit: 256 mb
用点阵表示数字,5*3的方格表示0~9,具体如下:
0的表示:
111
101
101
101
111
1的表示:
001
001
001
001
001
2的表示:
111
001
111
100
111
9的表示:
111
101
111
001
111
输入输出格式
输入描述:
输入一个数字串,用点阵输出。
输出描述:
按题意输出
输入输出样例
输入样例#:
02
输出样例#:
111111
101001
101111
101100
111111
题目来源
北京邮电大学2018年机试题
真题链接在此
思路:当时因为4和9的点阵,wrong了好几发,人傻了,所以注意一下。其它没什么,直接暴力大法。也可以开一个三维矩阵比我这个看着简洁一点。还有就是注意一下他的输出格式,他并不是以列输出二是以行输出,就是横向输出而不是纵向输出,所以要依次输出所有数字的每一行。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int main(){
int a0[5][3]={{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1}};
int a1[5][3]={{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}};
int a2[5][3]={{1,1,1},{0,0,1},{1,1,1},{1,0,0},{1,1,1}};
int a3[5][3]={{1,1,1},{0,0,1},{1,1,1},{0,0,1},{1,1,1}};
int a4[5][3]={{1,0,1},{1,0,1},{1,1,1},{0,0,1},{0,0,1}};
int a5[5][3]={{1,1,1},{1,0,0},{1,1,1},{0,0,1},{1,1,1}};
int a6[5][3]={{1,1,1},{1,0,0},{1,1,1},{1,0,1},{1,1,1}};
int a7[5][3]={{1,1,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}};
int a8[5][3]={{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,1,1}};
int a9[5][3]={{1,1,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1}};
char h[10000];
cin>>h;
int length=0;
int h2[10000];
for(int i=0;;i++){
if(h[i]!='\0'){
h2[length]=h[i]-'0';
length++;
}
else
break;
}
for(int i=0;i<5;i++){
for(int j=0;j<length;j++){
if(h2[j]==0){
for(int k1=0;k1<3;k1++)
cout<<a0[i][k1];
}
if(h2[j]==1){
for(int k1=0;k1<3;k1++)
cout<<a1[i][k1];
}
if(h2[j]==2){
for(int k1=0;k1<3;k1++)
cout<<a2[i][k1];
}
if(h2[j]==3){
for(int k1=0;k1<3;k1++)
cout<<a3[i][k1];
}
if(h2[j]==4){
for(int k1=0;k1<3;k1++)
cout<<a4[i][k1];
}
if(h2[j]==5){
for(int k1=0;k1<3;k1++)
cout<<a5[i][k1];
}
if(h2[j]==6){
for(int k1=0;k1<3;k1++)
cout<<a6[i][k1];
}
if(h2[j]==7){
for(int k1=0;k1<3;k1++)
cout<<a7[i][k1];
}
if(h2[j]==8){
for(int k1=0;k1<3;k1++)
cout<<a8[i][k1];
}
if(h2[j]==9){
for(int k1=0;k1<3;k1++)
cout<<a9[i][k1];
}
}
cout<<endl;
}
return 0;
}
C 、 发财数
Time Limit: 1000 ms
Memory Limit: 256 mb
一个大于等于2的整数,如果可以分解为8个或8个以上的素数相乘,则称其为发财数,让你输出第n个发财数
输入输出格式
输入描述:
输入一个整数t,代表有t组数据(t<1000)
输入一个正整数n,(n<=10000)
输出描述:
输出第n个发财数。
输入输出样例
输入样例#:
1
1
输出样例#:
256
题目来源
北京邮电大学2018年机试题
真题链接在此
思路:为了不超时,所以我先一次性找出了前10000个发财数并存储在一维数组中,然后根据输入随机访问一维数组即可。所以本题的重点是找出素数和发财数。根据规律我们可以发现,一个数如果是发财数,那么他的每一个因子都是素数,所以我们先可以找出前500个素数,然后从最小的素数开始依次判断当前数字对此素数取余是否等于0,如果等于0那么用该数字除以此素数然后继续进行,一直到等于1,如果过程中找不到一个素数因子那么可以判断此数字并不是发财数。这里一个可能超时的点就是找出前500个素数,这里我用到了欧拉筛(有兴趣的同学可以学习一下,以下代码直接给出了模板,时间复杂度是O(n)的,效率很高了)。关于为什么找出前500个素数即可,我是试出来的,因为大体思路就是如此,也可以多找一些,但是注意别超时。
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 10000000
using namespace std;
bool vis[maxn];
int prime[maxn],x;
void oulashai(int n) //欧拉筛
{
for(int i=2;i<=n;i++)
{
if(!vis[i]) prime[x++]=i;
for(int j=0;j<x;j++)
{
if(i*prime[j]>n) break;
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main(){
int t;
oulashai(6000);
cin>>t;
long long int m[10010];
int num=0;
for(int i=256;;i++){ //由题意可知,第一个发财数是256,所以从256开始依次向后寻找
int h1=0;
int h2=i;
int mark;
while(h2>0){
mark=0;
for(int j=0;j<500;j++){
if(h2%prime[j]==0){
h2/=prime[j];
h1++;
mark=1;
break;
}
}
if(mark==0){
break;
}
}
if(h2==1&&h1>=8){
m[num]=i;
num++;
}
if(num>10010)
break;
}
int n;
for(int k=1;k<=t;k++){
cin>>n;
cout<<m[n-1]<<endl;
}
return 0;
}
D 、 最长平衡串
Time Limit: 1000 ms
Memory Limit: 256 mb
给定只含01的字符串,找出最长平衡子串的长度(平衡串:包含0和1的个数相同)
输入输出格式
输入描述:
多组测试数据输入。
输入一串01字符串,字符串长度最大为100000。
输出描述:
请输出最长的平衡子串的长度。
输入输出样例
输入样例#:
101011000
输出样例#:
8
思路:动态规划,用数组dp来记录当前数组的值,一开始等于0,如果遇到了0就-1,遇到了1就+1,然后每生成一个数就要判断当前的dp中的数字是否是第一次出现,如果不是第一次出现,那么可以发现,此处和第一次当前数字出现的位置之间的串的长度就是一个平衡子串。具体讲解见链接。然后依次生成dp数组的值之后我们就可以进行比较了。注意这里用了map进行了映射,记录当前的数值是否是第一次出现。
#include<bits/stdc++.h>
using namespace std;
int main(){
string str;
while(cin>>str){
map<int,int> m;
int n=str.size();
int dp[n];
dp[0]=0;
for(int i=1;i<=n;i++){
if(str[i-1]=='0'){
dp[i]=dp[i-1]-1;
}else{
dp[i]=dp[i-1]+1;
}
}
int ans=0;
int b=0;
for(int i=1;i<=n;i++){
b = m[dp[i]];
if(b==0&&dp[i]!=0){ //表示当前的dp中存储的数字是第一次出现,所以要记录下来。
m[dp[i]]=i;
}
else{
if(i-b>ans){
ans=i-b;
}
}
}
cout<<ans<<endl;
}
}