昨天刚考完,oj上题目已经看不了了,不过交的代码都还在,趁热回忆一下
整体情况:
共169人,第四题全军覆没,8人3A,77人2A,40人1A,44人0A。
最后的排行榜(id截掉了):
problem A 二进制数字翻转
输入数据组数t
每组数据输入一个十进制数x(0<x<2^32),将其二进制位反转(共32位),然后输出对应的十进制数
签到题,唯一坑点就是int表示不了2^32-1吧,用long long就行了
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[32];
int main()
{int t,n,i;ll x;cin>>t;while(t--){memset(a,0,sizeof(a));cin>>x;i=0;do{a[i++]=x%2;x/=2;}while(x);ll re=0;for(i=0;i<32;i++){re=re*2+a[i];//低位变高位,相当于反转了}cout<<re<<endl;}return 0;
}
problem B 数字填充
就是用点阵表示数字,5*3的方格表示0~9,具体见样例及代码,0是然后输入一个数字串,用点阵输出
样例输入
02
样例输出
111111
101001
101111
101100
111111
这种暴力题我一开始是拒绝的==ctrl cv大法
每行用一个string表示,用存好的点阵数字相加起来然后输出就行了
AC代码:
#include<bits/stdc++.h>
using namespace std;
struct node{string s[5];
}num[10];
int main()
{int t,i,j;num[0].s[0]="111";//先存好0-9的点阵表示num[0].s[1]="101";num[0].s[2]="101";num[0].s[3]="101";num[0].s[4]="111";num[1].s[0]="001";num[1].s[1]="001";num[1].s[2]="001";num[1].s[3]="001";num[1].s[4]="001";num[2].s[0]="111";num[2].s[1]="001";num[2].s[2]="111";num[2].s[3]="100";num[2].s[4]="111";num[3].s[0]="111";num[3].s[1]="001";num[3].s[2]="111";num[3].s[3]="001";num[3].s[4]="111";num[4].s[0]="101";num[4].s[1]="101";num[4].s[2]="111";num[4].s[3]="001";num[4].s[4]="001";num[5].s[0]="111";num[5].s[1]="100";num[5].s[2]="111";num[5].s[3]="001";num[5].s[4]="111";num[6].s[0]="111";num[6].s[1]="100";num[6].s[2]="111";num[6].s[3]="101";num[6].s[4]="111";num[7].s[0]="111";num[7].s[1]="001";num[7].s[2]="001";num[7].s[3]="001";num[7].s[4]="001";num[8].s[0]="111";num[8].s[1]="101";num[8].s[2]="111";num[8].s[3]="101";num[8].s[4]="111";num[9].s[0]="111";num[9].s[1]="101";num[9].s[2]="111";num[9].s[3]="001";num[9].s[4]="111";cin>>t;while(t--){node re;string q;cin>>q;int ql=q.length();for(i=0;i<ql;i++)//每个数的每一行加起来{for(j=0;j<5;j++){re.s[j]+=num[q[i]-'0'].s[j];}}for(i=0;i<5;i++){cout<<re.s[i]<<endl;}}return 0;
}
problem C 发财数
一个大于等于2的整数,如果可以分解为8个或8个以上的素数相乘,则称其为发财数,让你输出第n个发财数(n最大到1w)
样例输入:
1
1
样例输出:
256
额...水平比较low没想到什么好的解法,暴力解决==用cin、cout是800ms,scanf、printf应该会快得多
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 400007//最大遍历到40w 就能找到第1w多个发财数
int vis[maxn],p[maxn];
ll fa[maxn];
void init(int n)//线性筛
{int pos=0;memset(vis,0,sizeof(vis));int i,j;for(i=2;i<n;i++){if(!vis[i]) p[pos++]=i;for(j=0;j<pos&&i*p[j]<n;j++){vis[i*p[j]]=1;if(i%p[j]==0) break;}}}int main()
{init(maxn);int t,n,i,k,j,q;vector <int> v;for(k=2;k<400000;k++)//遍历到40w {if(!vis[k]) continue;//是素数则直接跳过int kt=k;int anssize=0;int ansprime[30];int ansnum[30];for(i=0;i<1000;i++)//用前1000个素数来测试{//这个40w和1000,无脑试了很多次才确定这个范围,各位大佬有什么简便方法请指教 if(kt%p[i]==0)//素数分解,可以参考王道第四章的分解素因数 {ansprime[anssize]=p[i];ansnum[anssize]=0;while(kt%p[i]==0){ansnum[anssize]++;kt/=p[i];}anssize++;if(kt==1) break;}}int su=0;for(i=0;i<anssize;i++){su+=ansnum[i];}if(su>=8)//是发财数就存起来 {v.push_back(k);}}int vs=v.size();cin>>t;while(t--){cin>>n;cout<<v[n-1]<<endl;}return 0;
}
problem D 最长平衡串
给定只含01的字符串,找出最长平衡子串的长度(平衡串:包含0和1的个数相同),串长最大十万
这个题呢,自己见识太少又想不出巧方法,只能O(n^2)暴力,可想而知TLE了
之后群里有大佬们讨论,把0换成-1然后用前缀和来做,也挺简单的吧,就怪自己太渣想不到
附两个类似题型链接
https://blog.csdn.net/became_a_wolf/article/details/48129073
http://www.bubuko.com/infodetail-2273733.html
2017蓝桥杯初赛最后一题也是前缀和:https://www.cnblogs.com/-citywall123/p/12337928.html
前三道题的运行时间:
写的代码很渣,大佬勿喷。。。本人菜鸟一个,没接触过acm,代码能力极差
总结:
对acm大佬望尘莫及五体投地!!!









![[NOIP2011 提高组] 铺地毯](https://img-blog.csdnimg.cn/img_convert/200273625fc5365e16de4d00c864c826.png)







