题目链接:http://cstest.scu.edu.cn/soj/contest/contest.action?cid=332
A: Miku's Boxes
Description
When Miku cleans up the warehouse, She finds some boxes. All the boxes are cube, and the width of the i-th box is Ci=2^ki. Now, Miku prepares to throw these boxes away, but throwing them one by one is terrible, so she decides to put all boxes into a big box and throws it. Miku finds that only when box A's width is less than box B's, A can be put into B, and 8 boxes which width is 2^(k-1) can be put into 1 box which width is 2^k particular.
Now, please help Miku calculate how big of a box she needs to put all boxes into.
(If the biggest boxes of these boxes can meet the conditions, Miku will use this box, otherwise she will make a new box. Details please refer to the Sample Input.)
Input
The first line of input T is the number of test case.
There are three lines of each test case.
First, a integers n, means Miku find n different boxes.( 0 < n <= 50000)
Second, n intergers, k1, k2 ... kn, and ki means the i-th different box's width is 2^ki(0<=ki<=50000).
Third, n intergers, m1, m2 ... mn, and mi means the number of the i-th different box (1<=mi<=10000).
Output
For each test case output a interger K means the box's width is 2^K which Miku needs.
Sample Input
2
1
0
8
2
0 1
8 1
Sample Output
1
1
Hint
In test 1,Miku make a new box of 1 width.
In test 2,Miku use the 1 width's box her find in warehouse.
Author
qw4990
题意:给你一系列正方体盒子的边长2^k[i],及其相应个数m[i],
求最终用一个盒子的边长:2^a,该盒子可以一次性把一种正方体盒子全部装进去
解题方法:
法一:
/*目的:求A,其中A是这样定义的:最大的正方体边长为2^A思路:利用两点:一~最终要求的始终是正方形,Vmax=(2^A)^3=2^(A*3);
二,利用幂的乘法的优越性可避免大数相乘;
步骤:
1,化2^j=i;将小正方体个数j化为f[j]=i表示为(2^i>=j&&2^(i-1)<j)(这样做的目的是使多余部分也能整合成正方体)
2,求每种正方体可以放进的最小正方体箱子。Vi=2^(3*k[i]+f[m[i]]+2)=2^(3*Ai),即Ai=(3*k[i]+f[m[i]]+2)/3;
3,一步步比较求A
*/#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std
;const int maxn=50000+10;
int k[maxn],m[maxn],f[maxn];
int main()
{ int n,i,j,max,t,ans;
int T; scanf("%d",&T);
f[1]=0; t=1; i=1;
while(t<=10000) //这里的f[j]=i表示为(2^i>=j&&2^(i-1)<j)
{ for(j=t+1;j<=t*2;j++)
{f[j]=i; //printf("f[%d]=%d\n",j,i);
} t=t*2; i++;}
while(T--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&k[i]);
for(j=0;j<n;j++)
scanf("%d",&m[j]);
max=0;
for(i=0;i<n;i++)
{
ans=(3*k[i]+f[m[i]]+2)/3;//根据幂的乘法性质可得
//printf("%d ",ans);
if(max<ans)
max=ans;
}
printf("%d\n",max);
}
return 0;
}
法二:其实也是利用了以上的性质,只不过是直接推出最终结果的
#include<stdio.h>
#include<iostream>
#include<fstream>
using namespace std;
#define maxn 50009
int k[maxn],m[maxn],n;
int main()
{
int t;
cin >> t;
while(t--)
{
cin >> n;
for(int i=1;i<=n;i++)
cin >> k[i]; //输入正方体边长(2^k[i])
for(int i=1;i<=n;i++)
cin >> m[i];//个数
int ans = -1;
for(int i=1;i<=n;i++)
{
int K = k[i],tmp = 1;
while(tmp < m[i])
{
tmp *= 8;//因为8=2^3,V=2^((K+1)*3)=2^(K*3)*8=2^(k[i]*3)*(tmp*8);
K++;//边长取最大值
}
ans = max(ans,K);
}
cout << ans << endl;
}
return 1;
}