第一次蓝桥杯,没有考好,太久没有做oi赛制了,感觉自己太过于谨慎,以至于做题速度太慢。写篇题解纪念一下。
256MB的内存空间开一个数组,数组的每个元素都是32位二进制整数,如果不考虑程序占用的空间和维护内存需要的辅助空间,请问256MB的空间可以存储多少个32位二进制整数。
一字节(1B)有8比特,一个32位整数有32比特,256 * 1024 * 1024 / 4即可
答案:67108864
有2021个0-9数字,从1开始拼整数,用完就不能再拼其他数字了,求最多可以拼到数字几?(从1开始连续拼整数)
从1开始,循环计算每一个数字的每位数出现的次数,直到有个数字使用次数超过2021,则当前数字不能被拼出来,答案即为上一个数字
答案:3181
附上代码
#include
using namespace std;
int cnt[10];
int main(){
for(int i=1;i;i++){
int x=i;
while(x){
cnt[x%10]++;
if(cnt[x%10]>2021){
cout<<i-1;
return 0;
}
x=x/10;
}
}
return 0;
}
给定平面上20x21个整点(x,y)|0<=x<20,0<=y<21,求这些点确定了多少条不同的直线?
枚举所有点对,构成一条直线,在表中查找直线,判断该直线是否曾经出现过即可,没有出现过则ans++,并将直线存入表中。那么如果唯一的表示一条线段呢?
y=kx+b?这里的k如果是double型的可能会出现精度误差,导致计算出错。(我就是这么错的,所以我的答案是48953,下次不敢了)
其实只要能够唯一的表示一条直线就可以了,我们可以采用最简分数来存储 k 和 b 。即 k 和 b 都有分子fz,和分母fm。为了确保唯一性,当k<0时,我们让fz为正,fm为负。
考虑到斜率不存在的情况,由于斜率不存在的直线肯定只有20条,我们直接不考虑斜率不存在的情况,即x2=x1,最后再加上20条即可。由于斜率=0的已知,顺便也不去计算斜率为0,直接最后加上21条斜率为0的直线即可。
答案:40257
附上代码:(需要跑个12s,可以set优化,自己尝试吧)
#include
using namespace std;
struct node{
int fz,fm;
}k[1000000],b[1000000];
long long kfz,kfm,bfz,bfm,ans;
int gcd(int a,int b){
if(b==0)return a;
else return gcd(b,a%b);
}
void check(){
if(kfz<0){
kfz=-kfz;
kfm=-kfm;
}
if(bfz<0){
bfz=-bfz;
bfm=-bfm;
}
for(int i=1;i<=ans;i++){
if(kfz==k[i].fz&&kfm==k[i].fm&&bfz==b[i].fz&&bfm==b[i].fm)return;
}
ans++;
k[ans].fz=kfz;
k[ans].fm=kfm;
b[ans].fz=bfz;
b[ans].fm=bfm;
//cout<
}
int main(){
long long t1,t2;
for(int x1=0;x1<20;x1++){
for(int y1=0;y1<21;y1++){
for(int x2=0;x2<20;x2++){
for(int y2=0;y2<21;y2++){
if(x1==x2)continue;
if(y2==y1)continue;
//处理k
t1=y2-y1;
t2=x2-x1;
kfz=t1/gcd(t1,t2);
kfm=t2/gcd(t1,t2);
//处理b
t1=(y1*kfm-kfz*x1);
t2=kfm;
bfz=t1/gcd(t1,t2);
bfm=t2/gcd(t1,t2);
check();
}
}
}
}
cout<<ans+20+21;
return 0;
}
给定n=2021041820210418,求有多少组L,W,H满足 n= L * W * H 。
ps:1 1 4 和 1 4 1为不同的两组方案。
代码如下:
#include
using namespace std;
struct node{
int x,y,z;
}p[10000];
int a[10]={0,2,3,3,3,5,7,11,13};
int goal=2*3*3*3*5*7*11*13,ans;
void dfs(int dep,long long x,long long y,long long z){
if(dep==9){
if(x*y*z!=goal)return;
for(int i=1;i<=ans;i++){
if(x==p[i].x&&y==p[i].y&&z==p[i].z)return;
}
ans++;
p[ans].x=x;
p[ans].y=y;
p[ans].z=z;
return;
}
dfs(dep+1,x*a[dep],y*a[dep],z*a[dep]);
dfs(dep+1,x*a[dep],y*a[dep],z);
dfs(dep+1,x*a[dep],y,z*a[dep]);
dfs(dep+1,x*a[dep],y,z);
dfs(dep+1,x,y*a[dep],z*a[dep]);
dfs(dep+1,x,y*a[dep],z);
dfs(dep+1,x,y,z*a[dep]);
dfs(dep+1,x,y,z);
}
int main(){
dfs(1,1,1,1);
cout<<ans;
return 0;
}
一张图有2021个结点,依次编号1-2021。如果a,b相差绝对值小于等于21,则a和b之间有一条长度为lcm(a,b)的无向边。求1到2021的最短路。
知道 lcm= i x j /gcd(i,j),且知道spfa,dij即可,是一道裸的最短路模板题
答案:10266837
代码如下(前向星存图,spfa板子)
#include
using namespace std;
struct edge{
int u,v,w,next;
}e[1000100];
int vex[100010],k,vis[100010],dis[100010];
queue<int>q;
void add(int u,int v,int w){
k++;
e[k].u=u;
e[k].v=v;
e[k].w=w;
e[k].next=vex[u];
vex[u]=k;
}
void spfa(){
for(int i=2;i<=2021;i++)dis[i]=1e9;
q.push(1);
while(!q.empty()){
int u=q.front();
vis[u]=0;
for(int i=vex[u];i;i=e[i].next){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(vis[v]==0){
vis[v]=1;
q.push(v);
}
}
}
q.pop();
}
cout<<dis[2021];
}
int gcd(int a,int b){
if(b==0)return a;
else return gcd(b,a%b);
}
int main(){
for(int i=1;i<=2021;i++){
for(int j=i+1;j<=i+21&&j<=2021;j++){
add(i,j,i*j/gcd(i,j));
add(j,i,i*j/gcd(i,j));
}
}
spfa();
return 0;
}
求0:00:00经过n毫秒后是几时几分几秒?不足两位要补前导0。n<=1e18
样例:
n=46800999 ,ans=13:00:00
n=1618708103123,ans=01:08:23
注意毫秒除以1000,再把天86400s余掉,求出经过的小时,分钟秒就可以了。
代码如下:
#include
using namespace std;
int main(){
long long n;
cin>>n;
n=n/1000;
n=n%86400;
int x=n/3600;
int y=(n-3600*x)/60;
int z=n-3600*x-y*60;
printf("%02d:%02d:%02d",x,y,z);
return 0;
}
求定一个天平和N个砝码,砝码重量分别为W1,W2,……,W N _{N} N
计算其一共可以称出多少种不同的重量?
N<=100, ∑ \sum ∑Wi<=100000
注:砝码可以放在任意一边
样例:N=3,W=1,4,6,ans=10
1,6-4,4-1,4,4+1,6,6+1,6+4-1,6+4,6+4+1
代码如下
#include
using namespace std;
int f[101][210010],a[101],base=1e5;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
f[0][0+base]=1;
for(int i=1;i<=n;i++){
for(int j=base+base;j>=0;j--){
if(f[i-1][j])f[i][j]=1;
if(j+a[i]<=2*base&&f[i-1][j+a[i]])f[i][j]=1;
if(j-a[i]>=0&&f[i-1][j-a[i]])f[i][j]=1;
}
}
int ans=0;
for(int i=1+base;i<=2*base;i++){
if(f[n][i])ans++;
}
cout<<ans;
return 0;
}
给定N,求N最早出现在杨辉三角的第几项
N<=1e9
样例:
N=6,ans=13
N=10,ans=18
代码如下
#include
using namespace std;
long long C[50000][500];
int main(){
long long n;
cin>>n;
if(n==1){
cout<<1;
return 0;
}
if(n==2){
cout<<5;
return 0;
}
C[0][0]=1;
C[1][0]=1;
C[1][1]=1;
for(long long i=2;i<50000;i++){
C[i][0]=1;
C[i][1]=i;
C[i][2]=i*(i-1)/2;
if(n<C[i][2])break;
if(n==C[i][1]){
cout<<i*(i+1)/2+2;
return 0;
}
if(n==C[i][2]){
cout<<i*(i+1)/2+3;
return 0;
}
for(long long j=3;j<=i;j++){
C[i][j]=C[i-1][j-1]+C[i-1][j];
if(C[i][j]>n)break;
if(C[i][j]==n){
cout<<i*(i+1)/2+j+1;
return 0;
}
}
}
cout<<n*(n+1)/2+2;
return 0;
}