AtCoder Beginner Contest 085 C Otoshidama(计算机整数乘法问题+方程求解)

本文针对一个有趣的新年红包问题进行了解析,通过不同数量的10000元、5000元和1000元纸币,探讨如何组成特定总金额的可能性。提供了三种不同的循环解决方案,包括三重循环、二重循环和一重循环的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Statement
The commonly used bills in Japan are 10000-yen, 5000-yen and 1000-yen bills. Below, the word "bill" refers to only these.


According to Aohashi, he received an otoshidama (New Year money gift) envelope from his grandfather that contained N bills for a total of Y yen, but he may be lying. Determine whether such a situation is possible, and if it is, find a possible set of bills contained in the envelope. Assume that his grandfather is rich enough, and the envelope was large enough.


Constraints
1≤N≤2000
1000≤Y≤2×107
N is an integer.
Y is a multiple of 1000.
Input
Input is given from Standard Input in the following format:


N Y
Output
If the total value of N bills cannot be Y yen, print -1 -1 -1.


If the total value of N bills can be Y yen, let one such set of bills be "x 10000-yen bills, y 5000-yen bills and z 1000-yen bills", and print x, y, z with spaces in between. If there are multiple possibilities, any of them may be printed.


Sample Input 1
Copy
9 45000
Sample Output 1
Copy
4 0 5
If the envelope contained 4 10000-yen bills and 5 1000-yen bills, he had 9 bills and 45000 yen in total. It is also possible that the envelope contained 9 5000-yen bills, so the output 0 9 0 is also correct.


Sample Input 2


20 196000
Sample Output 2


-1 -1 -1
When the envelope contained 20 bills in total, the total value would be 200000 yen if all the bills were 10000-yen bills, and would be at most 195000 yen otherwise, so it would never be 196000 yen.


Sample Input 3


1000 1234000

Sample Output 3

14 27 959

There are also many other possibilities.


Sample Input 4


2000 20000000
Sample Output 4


2000 0 0

题意:类似百马百担,纸币有10000元 5000元 1000元 给出n张 y元,求出一种可以达成上述条件的3种纸币的张数即可。

思路:暴力循环即可

1.三重循环(这是最傻也是最耗时的循环)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <stack>
#define N 1005
using namespace std;
typedef long long ll;
int main()
{
    int n,y;
    scanf("%d%d",&n,&y);
    int a=1000,b=5000,c=10000;
    int s1=-1,s2=-1,s3=-1,n1,n2,n3;
    if(n*1000>y||n*10000<y)
        s1=-1,s2=-1,s3=-1;
    else
    {
        n3=y/c;
        for(int i=n3; i>=0; i--)
        {
            int flag=0;
            n2=(y-i*10000)/5000;
            for(int j=n2; j>=0; j--)
            {
 
                n1=(y-i*10000-j*5000)/1000;
                    for(int k=n1; k>=0; k--)
                    {
 
                        if(i+j+k==n&&i*c+j*b+k*a==y)
                        {
                            s1=k,s2=j,s3=i;
                            flag=1;
                            break;
                        }
                    }
                    if(flag)
                        break;
 
 
            }
            if(flag)
                break;
        }
    }
    printf("%d %d %d\n",s3,s2,s1);
 
}
2.二重循环

(在三重循环的基础上仅仅改变了最后一重循环,因为仔细观察最后一重循环完全是多余的,直接判断即可,但是由于个人对计算机乘法运算不敏感,所以。。。。)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <stack>
#define N 1005
using namespace std;
typedef long long ll;
int main()
{
    int n,y;
    scanf("%d%d",&n,&y);
    int a=1000,b=5000,c=10000;
    int s1=-1,s2=-1,s3=-1,n1,n2,n3;
    if(n*1000>y||n*10000<y)
        s1=-1,s2=-1,s3=-1;
    else
    {
        n3=y/c;
        for(int i=n3; i>=0; i--)
        {
            int flag=0;
            n2=(y-i*10000)/5000;
            for(int j=n2; j>=0; j--)
            {
 
                n1=(y-i*10000-j*5000)/1000;
                if(i+j+n1==n&&i*c+j*b+n1*a==y)
                {
                    s1=n1,s2=j,s3=i;
                    flag=1;
                    break;
                }
 
 
            }
            if(flag)
                break;
        }
    }
    printf("%d %d %d\n",s3,s2,s1);
 
}
3.一重循环:

2个三元一次方程,消掉一个未知数,仅剩2个未知数,一个循环,另一个利用乘法规则求解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <stack>
#define N 1005
using namespace std;
typedef long long ll;

int main()
{
    int n,y;
    while(scanf("%d%d",&n,&y)==2){
       int a=y/10000,s1=-1,s2=-1,s3=-1;
       for(int i=a;i>=0;i--){
        int j=(y-1000*n-9000*i)/4000;
        if(i*9000+4000*j==y-1000*n&&i+j<=n&&i>=0&&j>=0)
        {
            s1=i,s2=j,s3=n-i-j;
            break;
        }
       }
       printf("%d %d %d\n",s1,s2,s3);

    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值