继续补上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.
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)不过数据很小可以过
{
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种可能即可~~
{
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.
然后按照这种思想很容易得到第一种方法:
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) 之内可以完成
其他的方法:
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;