【NOIP】入门题题解— —小玉买文具、P老师买铅笔

author:&Carlton

tags:NOIP,模拟题,语言基础练习题

language:C++

website:洛谷能力提升综合题单Part1 入门阶段 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

date:2023年7月10日


P1421 小玉买文具

简单的入门题,题解思路也类似

#include <iostream>
using namespace std;

int main()
{
    int a,b;
    cin >> a >> b;
    int n;
    n=(10*a+b)/19;        //int数据类型去掉小数点,解决除不尽带来的问题
    cout << n << endl;
    return 0;
}

P1909 买铅笔

我想到的的思路是两个:

        ①直接相除,计算购买各个包装所需的袋数,再特别处理带有小数点的情况(用整数部分乘回去和原值对比

        ②在处理小数点情况中 通过数据类型 实型 和 整型 对比,判断是否相等

👇这是①的源代码

#include <iostream>
using namespace std;

int compare(int num,int n,int a)
{
    if(num*a<n)                //乘回去对比数据,从而判断是否有舍去小数部分
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int main()
{
    int n,a1,p1,a2,p2,a3,p3;    //a:amount p:price
    cin >> n >> a1 >> p1 >> a2 >> p2 >> a3 >> p3;
    int num1,num2,num3;
    num1=n/a1;
    num2=n/a2;
    num3=n/a3;
    if(compare(num1,n,a1))
    {
        num1++;
    }
    if(compare(num2,n,a2))
    {
        num2++;
    }
    if(compare(num3,n,a3))
    {
        num3++;
    }
    int price1,price2,price3;
    price1=num1*p1;
    price2=num2*p2;
    price3=num3*p3;
    int min;                     //再对比得出最小值
    min= price1<=price2 ? price1 : price2;
    min= min<=price3 ? min : price3;
    cout << min;
    return 0;
}

看到三个感觉不错的题解:

        两个是优化:

        处理小数情况的思路方面的:

        通过取余运算判断是否有舍去小数,从而分情况处理。        

        

#include <stdio.h>
int main()//我是萌新,轻喷,求指教
{//很清新,很通俗易懂吧!
   int n,a1,a2,b1,b2,c1,c2,a,b,c,z;
   scanf("%d",&n);//n是需要的数量
   scanf("%d %d",&a1,&a2);//a1是数量,a2是价格
   scanf("%d %d",&b1,&b2);
   scanf("%d %d",&c1,&c2);
   a=n/a1;a1=n%a1==0?a:a+1;a=a1*a2;//第一和第二表达式求至少需要买的铅笔包数,第三给表达式表示总共需要的价格
   b=n/b1;b1=n%b1==0?b:b+1;b=b1*b2;//同上
   c=n/c1;c1=n%c1==0?c:c+1;c=c1*c2;//同上
   if(a<b&&a<c)z=a;//取最省钱的方案,赋值给z
   if(b<a&&b<c)z=b;
   if(c<b&&c<a)z=c;
   printf("%d\n",z);
   return 0;
}

        

        整个程序执行性能方面的:

        用位运算快速倍增,再微调得到结果

    #include<cstdio>
    using namespace std;
    int i,j,k,n,m,w,ans;
    int main(){
        scanf("%d",&n);
        for(i=0;i<3;i++){
            scanf("%d%d",&j,&k);m=j;w=k;//输入并存下初始的价格与数量
            while(j<n){j<<=1;k<<=1;}//价格与数量不断*2直到数量大于n
            while(j>n){j-=m;k-=w;}//*2有可能导致买太多了,减去一些
            while(j<n){j+=m;k+=w;}//减去之后又可能太少了,加上一些
            //其实就是大幅度地上调,然后做一些微调
            if(k<ans||ans==0)ans=k;//判断是否是最小花费
        }
        printf("%d\n",ans);
        return 0;//输出并返回
    }

        另一个是思路上不一样:

        通过循环累加到满足铅笔数量条件,得到要花费的钱

       

#include<bits/stdc++.h>
using namespace std;
long n,a1,a2,b1,b2,c1,c2,pen1,pen2,pen3,x[3];
int compare(int a1,int a2,int b1,int b2,int c1,int c2)
{
    while(pen1<n)  { pen1+=a1; x[0]+=a2; }
    while(pen2<n)  { pen2+=b1; x[1]+=b2; }
    while(pen3<n)  { pen3+=c1; x[2]+=c2; }
    return x[0],x[1],x[2];
}
int main()
{
    cin>>n>>a1>>a2>>b1>>b2>>c1>>c2;
    compare(a1,a2,b1,b2,c1,c2);
    sort(x,x+3);
    cout<<x[0];
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值