昨天刚考完,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
前三道题的运行时间:
写的代码很渣,大佬勿喷。。。本人菜鸟一个,没接触过acm,代码能力极差
总结:
对acm大佬望尘莫及五体投地!!!