TopCoder Srm671 一二题翻译及题解

1  染色(paint

现有W*H的棋盘格子,要在其上用蓝色染其中的一些格子,形成一个蓝色的矩形。由于费用问题,你最多只能染色M个格子,请问你能染色的矩形最大面积是多少?

【输入格式】(paint.in)

   1行:2个整数WH,范围在[1…10^6]

   2行:1个整数M,范围在[1…10^12]

 

【输出格式】(paint.out)

一个整数,可能的矩形最大面积。

 

【输入输出样例】

输入

输出

3  5

14

12

4  4

10

9

1000000  1000000

999999999999

999999000000

 

【分析】

这显然是一道很简单的题,但是我交的时候竟然错了三次,有一次是因为没有考虑到M>W*H的情况,有两次是因为没有去掉测试的语句。这一道题最直观的思路就是枚举所有的W和H,求出所有的面积,并取一个小于M又最大的情况。不过显然可以观察到只需枚举W或H即可,因为M/W就是以当前的W为一边的最大又不超过M的矩形面积的另一边长度。当然,还要判断一下M/W是否超过H,如果超过就不行了,就放不下了。当然要注意另一点:当M>W*H时,怎样枚举都是找不出来的,则直接输出W*H就好了。

【代码】

# include <cstdio>
# include <iostream>
using namespace std;
unsigned long long int w,h;
unsigned long long int m,i;
unsigned long long int MaxAns = 0;
int main(){
freopen("paint.in","r",stdin);
freopen("paint.out","w",stdout);
ios::sync_with_stdio(false);
cin >> w >> h;
cin >> m;

if (w * h <= m){
cout << w * h << endl;
return 0;
}
for (i=1;i<=w;++i){
if (MaxAns < (m/i)*i && m/i <= h){
MaxAns = (m/i)*i;
}
}
cout << MaxAns << endl;
}



 

2  飞镖(dart

小明喜欢玩飞镖游戏,他会把每次的得分都记录在数组中。今天有个飞镖大奖,得奖的规则是:如果你4次飞镖的得分先后是(a,b,c,d),满足a*b*c = d

小明准备把记录里的其他项删除,只留下满足获奖条件的4个分数,他想问你有多少种不同方案?

【输入格式】(dart.in)

   1行:1个整数N

   2行:N个整数,每个整数范围在[1…10^6]

 

【输出格式】(dart.out)

一个整数,方案数。

 

【输入输出样例】

输入

输出

6

10  2  2  7  40  160

2

注:(10,2,2,40)(2,2,40,160)

8

128  64  32  16  8  4  2  1

0

21

2  3  4  5  6  8  12  16  20  24  40  24  20  16  12  8  6  5  4  3  2

3

 

N范围】

80%[4…500],

 100%[4…2000]

 【分析】

这一道题最基本的解法(最直观的)是枚举a,b,c,并判断a*b*c是否在数组中存在,这可以用一个计数排序的思想(或者哈希表)用O(1)的时间判定a*b*c是否存在(还要判定a*b*c是否小于10^6),就可以过80%的数据。而满分算法,则是找到a*b和d/c的对应性,因为若a*b=d/c,则a*b*c=d,所以可以得出一个O(n^2)的题解。

只不过要注意一点:在联赛的时候,因为系统的不同,scanf对于Linux与Windows中long long的读入所用的方式是不同的。举个例子,假如a是long long,用scanf读入时,在Linux下是scanf("%lld",&a);,Windows下是scanf("%I64d",&a);。考试时要注意这个不同。

【代码】

# include <cstdio>
using namespace std;
const int MAXN = 2000;
const int Pow10_6 = 1000000;
int show[Pow10_6 + 2];
int num[MAXN + 1];
int main(){

freopen("dart.in","r",stdin);
freopen("dart.out","w",stdout);

int n;
long long Ans = 0;
scanf("%d",&n);
for (int i=0;i!=n;++i){
scanf("%d",&num[i]);
}

for (int i=2;i!=n;++i){ //Find b
for (int j=i-2;j>=0;--j){
//Find a
if ((long long )num[i-1] * (long long)num[j] <= Pow10_6){
//Could Put Inside(Means May Have a Number d that a*b*c=d)
++show[(long long)num[i-1] * (long long)num[j]];
}
}

for (int j=i+1;j!=n;++j){
//Find d
if (num[j] % num[i] == 0){
Ans += show[num[j] / num[i]];
}
}
}

printf("%I64d\n",Ans);
}



 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值