第一题:阶乘之和
描述
给你一个非负数整数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);
}
}