ACM分享第二周

第一题:阶乘之和

描述

给你一个非负数整数n,判断n是不是一些数(这些数不允许重复使用,且为正数)的阶乘之和,如果9=1!+2!+3!,如是是,则输出Yes,否则输出No;

输入

第一行有一个整数0<m<100,表示有m组测试数据;
每组测试数据有一个正整数n<1000000;

输出

如果符合条件,输出Yes,否则输出No;

样例输入

2
9
10

样例输出

Yes
No

解题思路

我一开始的想法是先定义一个求阶乘的调用函数,方便在主函数中进行调用。在主函数中,从i=n/2开始进行判断n是否大于i,因为大于n/2的阶乘必定大于n,可以不作考虑。
然后i依次减1,如果i!<n则n=n-i!,否则直接i--,继续循环,直至i>=1或n==0结束循环.
如果n==0则表示Yes,否则为No。然而最后结果却是TimeLimitExceeded。
之后,由于题目中要求n<1000000,则可以直接用数组表示1-9满足题意的阶乘,如此便没再超时。

我的代码

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int m;
    long long n,i;
    long long k[10]={0,1,2,6,24,120,720,5040,40320,362880};//满足题意的阶乘,从0开始
    scanf("%d",&m);
    while(m--)
    {
        scanf("%lld",&n);
        int flag=0;
        for(i=9;i>=1;i--)
        {
            if(n>=k[i]&&n>0)
               n-=k[i];
            if(n==0)//找到符合题意的阶乘
                flag = 1;
        }
        if(flag)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

第二题:寻找最大数(三)

描述

给出一个整数N,每次可以移动2个相邻数位上的数字,最多移动K次,得到一个新的整数。
求这个新的整数的最大值是多少。

输入

多组测试数据。
每组测试数据占一行,每行有两个数N和K(1<=N<=10^18;0<=K<=100).

输出

每组测试数据的输出占一行,输出移动后得到的新的整数的最大值。

样例输入

1990 1
100 0
9090000078001234 6

样例输出

9190
100
9907000008001234

解题思路

我一开始对题意理解错了,误以为只能两个相邻数一起移动k次。后来发现不是这样的,题意是一个数移动不能跳着移动,只能和相邻数位发生交换进行移动,并且最多可移动交换k次。
这样的话,自然要找最大值进行左移,才能得到最大值。从第一位数开始,找到k+1长度中的最大值,将之移动到首位,此时可移动次数k值也要相应减少。接着从第二位数开始,重复上述操作,直至第k+1个长度中的第一位等于数组长度,或者k值减为0.
另外,要注意数组是从0开始的,k+1长度移动可k次。

我的代码

#include <stdio.h>
#include <string.h>

int main()
{
    char str[20], temp;
    int k, len, i, flag1, flag2;
    while(scanf("%s%d", str, &k) != EOF)
    {
        len = strlen(str);
        flag1 = flag2 = 0;//flag2代表最大数字下标值,flag1为k+1长度内起始下标
        while(k > 0)
        {
            if(flag1 == len)//字符串长度=k+1长度起始下标值,不可能再有移动,退出
            {
                break;
            }
            for(i = flag1; i <= flag1 + k && i < len; i++)//寻找k+1长度内最大值下标,赋予flag2
            {
                if(str[i] > str[flag2])
                {
                    flag2 = i;
                }
            }
            if(flag2 > flag1)//最大值的下标大于k长度起始下标
            {
                k -= (flag2 - flag1);//k代表剩余可移动次数
                for(i = flag2; i > flag1; i--)//将最大值移到开始位置,其余依次后移
                {
                    temp = str[i];
                    str[i] = str[i - 1];
                    str[i - 1] = temp;
                }
            }
            flag1++;
            flag2 = flag1;//再次开始新的移动,直至k=0
        }
        puts(str);
    }
    return 0;
}

第三题:Greedy Mouse

描述

A fat mouse prepared M pounds of cat food,ready to trade with the cats guarding the warehouse containing his favorite food:peanut. The warehouse has N rooms. The ith room contains W[i] pounds of peanut and requires F[i] pounds of cat food. Fat mouse does not have to trade for all the peanut in the room, instead, he may get W[i]*a% pounds of peanut if he pays F[i]*a% pounds of cat food. The mouse is a stupid mouse, so can you tell him the maximum amount of peanut he can obtain.

输入

The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers W[i] and F[i] respectively. The test case is terminated by two -1. All integers are not greater than 1000.

输出

For each test cases, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of penaut that Fat Mouse can obtain.

样例输入

5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1

样例输出

13.333
31.500

解题思路

我理解的题意是这样的:老鼠一开始共有猫粮M,共有N个仓库,每个仓库内有w[i]的花生,需要F[i]的猫粮来换,可以不必换完。求最大能换来的花生。
对于这类题,应该先找价值最大的来换,直到将猫粮用完。

我的代码

#include<stdio.h>  
#include<iostream>  //方便调用soft函数
#include<string.h>  
#include<algorithm>  
#include<cmath>  
using namespace std;  

struct mouse  //用结构体会更方便
{  
    int w,f;  //一个房间内的花生和需要的猫粮
    double rate;  //单位猫粮能换到的花生
}p[1005];  

int cmp(mouse a,mouse b)  
{  
    return a.rate>=b.rate;  
}  

int main()  
{  
    int m,n;  
    while(scanf("%d%d",&m,&n))  
    {  
        if(m==-1&&n==-1)  //都为-1时退出
            break;  
        for(int i=0;i<n;i++)  
        {  
            scanf("%d%d",&p[i].w,&p[i].f);  //输入第i个房间内的花生和需要的猫粮
            p[i].rate=p[i].w*1.0/p[i].f;  //注意乘以1.0,否则相除会取整
        }  

        sort(p,p+n,cmp);  //按照单位比从大到小的顺序排列,w、f也会对应排列

        double sum=0;  //能换到的花生数
        for(int i=0;m>0&&i<n;i++)  //在老鼠还有猫粮的条件下
        {  
            if(p[i].f<=m)  //剩余猫粮数大于第i个房间内的猫粮,也就是说可以将这个房间内的花生全部换完
            {  
                sum+=p[i].w;  
                m-=p[i].f;  //猫粮数相应减少
            }  
            else  
            {  
                sum += m*p[i].rate;  //剩余猫粮数小于第i个房间内的猫粮,按比例进行交换至无剩余猫粮
                break;  
            }  
        }  
        printf("%.3lf\n",sum);  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值