继续补上srm的总结:
250pt
Problem Statement
Desertification (the process of good land turning into desert) is a severe problem on Bob's island. Bob's island is a rectangular grid of cells. You are given a vector <string> island that shows the current state of Bob's island. The j-th character of the i-th element of island is 'D' if cell in row i, column j of the grid is desert and is 'F' if this cell is forest.
The desert spreads each year as follows:
- If a cell is desert, it remains desert forever.
- If a cell is forest and it is adjacent to at least one desert cell (in one of the four orthogonal directions), it becomes desert after one year.
- Otherwise the cell remains forest for another year.
Return the number of desert cells after
T years.
Definition
Class:
Desertification
Method:
desertArea
Parameters:
vector <string>, int
Returns:
int
Method signature:
int desertArea(vector <string> island, int T)
(be sure your method is public)
Constraints
-
island will contain between 1 and 10 elements, inclusive.
-
Each element of island will contain between 1 and 10 characters, inclusive.
-
Each character in island will be 'D' or 'F'.
-
Each element of island will contain the same number of characters.
-
T will be between 1 and 1,000,000,000, inclusive.
记得当时写了遍历,如果一个是沙漠则把周围的都设置为沙漠,这样牵涉到一个问题,循环到某年时候遇到的可能是刚刚变成沙漠的,因此需要每次用一个Vector<string> 记录新的。
其实对每一个来计算在其T距离内有没有沙漠即可,复杂度 O(n^4)不过数据很小可以过
Code Snippet
int desertArea(vector <string> land, int T)
{
int r= land.size(); int c = land[0].size();
int cnt=0;
REP(i,r)REP(j,c) {
if(land[i][j] == 'D') {cnt++;continue;}
bool tag=false;
REP(x,r){
if(tag)break;
REP(y,c){
if(land[x][y]=='D'&&abs(x-i)+abs(y-j)<=T){
tag=true;break;
}
}
}
if(tag)cnt++;
}
return cnt;
}
500pt
Problem Statement
John is playing with balls. All of the balls are identical in weight and considered to have a zero radius. All balls are located on the same straight line and can move only along this line. If a ball rolling to the right and a ball rolling to the left at the same speed collide, they do not change speed, but they change direction.
You are given vector <int> x. x[i] is the initial position of the i-th ball. John decides the direction for each ball (right or left) with equal probability. At time 0, he rolls the balls in the chosen directions simultaneously at a speed of one unit per second. Return the expected number of bounces between all balls during T seconds (including those collisions that happen exactly at T seconds).
Definition
Class:
BouncingBalls
Method:
expectedBounces
Parameters:
vector <int>, int
Returns:
double
Method signature:
double expectedBounces(vector <int> x, int T)
(be sure your method is public)
Notes
-
There is no friction. Each ball continues rolling at the same speed forever.
-
Your return value must have an absolute or relative error less than 1e-9.
Constraints
-
x will contain between 1 and 12 elements, inclusive.
-
Each element of x will be between 0 and 100,000,000, inclusive.
-
All elements of x will be distinct.
-
T will be between 1 and 100,000,000, inclusive.
Examples
蛮有意思的题,只需要注意到,两个球碰撞后立即反向,而且速度不变,可以看做两个球穿越····然后枚举所有可能的方向2^n种可能即可~~
Code Snippet
class BouncingBalls
{
public:
double expectedBounces(vector <int> x, int T)
{
int n = x.size();int ans=0;
sort(x.begin(),x.end());
REP(i,(1<<n)){
int mask=1;
vector<int> vec(n);
for(int k=0;k<n;k++,mask<<=1){
if(mask&i)vec[k] = x[k] + T;
else vec[k] = x[k] - T;
}
for(int a=0;a<n;a++)
for(int b=a+1;b<n;b++){
if(vec[a]>=vec[b])ans++;
}
}
return double(ans)/(1<<n);
}
500分和250分的基本都会用到一些简化的思想,化复杂为简单,化特殊为一般~
1000pt
Problem Statement
You are given six integers, minx, maxx, miny, maxy, minz and maxz. Return the number of triplets of integers (x,y,z) that satisfy the following three conditions:
- x is between minx and maxx, inclusive.
- y is between miny and maxy, inclusive.
- z is between minz and maxz, inclusive.
- x * y = z
Definition
Class:
ProductTriplet
Method:
countTriplets
Parameters:
int, int, int, int, int, int
Returns:
long long
Method signature:
long long countTriplets(int minx, int maxx, int miny, int maxy, int minz, int maxz)
(be sure your method is public)
Constraints
-
maxx will be between 1 and 1,000,000,000, inclusive.
-
maxy will be between 1 and 1,000,000,000, inclusive.
-
maxz will be between 1 and 1,000,000,000, inclusive.
-
minx will be between 1 and maxx, inclusive.
-
miny will be between 1 and maxy, inclusive.
-
minz will be between 1 and maxz, inclusive.
贴一下tutorial中的解释,挺明白:
The problem asks about the number of triplets of integers (x, y, z), such that
x1 ≤ x ≤ x2
y1 ≤ y ≤ y2
z1 ≤ z ≤ z2
and x * y = z
Let's look at a special case of the problem. Given a fixed x0. Calculate the number of integer triplets (x0, y, z), such that
y1 ≤ y ≤ y2
z1 ≤ z ≤ z2
and x0 * y = z
The conditions on z will derive the following conditions on y.
z1 ≤ x0 * y ≤ z2
z1/x0 ≤ y ≤ z2/x0
ceil(z1/x0) ≤ y ≤ floor(z2/x0)
Another condition on y is y1 ≤ y ≤ y2. So, max(y1, ceil(z1/x0)) ≤ y ≤ min(y2, floor(z2/x0)) are the only limiting conditions on y and z, because any value of y in this range will give a valid (x0, y, z) triplet.
The number of candidate values to y is: min(y2, floor(z2/x0))-max(y1, ceil(z1/x0))+1, provided that the result of the subtraction is not negative. i.e.: the interval is not empty.
然后按照这种思想很容易得到第一种方法:
Code Snippet
int64 cacl(int x,int miny,int maxy,int minz,int maxz){
minz = max(minz,x*x+1);
if(minz>maxz)return 0;
miny = max(miny,(minz+x-1)/x);
maxy = min(maxy,maxz/x);
return max(0,maxy-miny+1);
}
class ProductTriplet
{
public:
long long countTriplets(int minx, int maxx, int miny, int maxy, int minz, int maxz)
{
int64 ans=0;
for(int64 i=minx;i<=maxx && i*i<maxz ;i++)
ans+=cacl(i,miny,maxy,minz,maxz);
for(int64 i=miny;i<=maxy && i*i<maxz ;i++)
ans+=cacl(i,minx,maxx,minz,maxz);
for(int64 i=max(minx,miny);i<=min(maxx,maxy) && i*i<=maxz;i++)
if(i*i>=minz)ans++;
return ans;
}
首先计算出x<sqrt(z) 然后y<sqrt(z) 最后x==y
注意cacl 中首先要更新minz至少为x*x+1保证x<y;
关键是想到x*y=z直接枚举会超时,但是分别枚举x,y 均在sqrt(z) 之内可以完成
其他的方法:
Code Snippet
int64 cacl2(int x1,int x2,int y1,int y2,int z1,int z2){
int x=x1,y=y1;
int64 ans=0;
while(x<=x2 && y<=y2 && x*y<=z2){
int low = (z1+x-1)/x ;
int high = z2/x;
low = max(y,low);
high = min(y2,high);
if(high>=low)ans+=(high-low+1);
x++;
if(high-low<100)
swap(x,y),swap(x2,y2);
}
return ans;
}
int64 cacl(int x1,int x2,int y1,int y2,int z){
if(z==0)return 0;
int x=x1,y=y1;
int64 ans=0;
while(x<=x2 && y<=y2 && x*y<=z){
if(x>y){
swap(x2,y2);swap(x,y);
}
int k = z/x ;
int low = max(1,y);
int high = min(y2,k);
if(high>=low)ans+=(high-low+1);
x++;
}
return ans;
}
class ProductTriplet
{
public:
long long countTriplets(int minx, int maxx, int miny, int maxy, int minz, int maxz)
{
int64 ans = cacl(minx,maxx,miny,maxy,maxz);
return ans-cacl(minx,maxx,miny,maxy,minz-1);
/*return cacl(minx,maxx,miny,maxy,minz,maxz2);*/
}
一种使用cacl函数,计算1 ~maxz的可用对数,然后减去1~(minz-1)的可用对数即可
计算过程中,枚举x的值,如果x>y则swap(x,y)其实也是保证枚举次数不超过sqrt(z)
另一种方法使用cacl2函数直接计算结果,同样枚举x的值,不过在得到的y的值小于一定大小
->100 的时候交换x和y,这是基于此时枚举y值可能更有效率而来的。
在计算ceil(x) 时候有点技巧 low = (z-1+x)/x;