农场主约翰喜爱对称的事物,眼下他准备把他牧场里的牛放置到N∗M(1≤N≤1,000,000,000; 1≤M≤1,000,000,000)的格子里。为了保持对称性,他用下面的方法放置牛。先放一只牛到牧场的中心格子,如果没有这样的中心格子,他就停止他放置的工作。然后他将牧场分割成四个相同大小的区域(这四个区域被正中心的那只牛所在的行和列所分隔),并将牛用上面的方法安排到四个区域中。他不断地重复着他的分割直到没有中心方格存在或者牧场不能再被细分为止。看下面的例子,如果N=7,M=15,那么约翰将在第4行,第8列放置一头牛并且将牧场分割成四个3∗7的区域。在每一个3∗7的区域的第2行,第4列放置一头牛,并且再将每个区域分割成四个1∗3的区域。放置的过程如下所示(C代表一只牛):
这个牧场必须放置21头牛。另一个例子,如果N=M=5,约翰只需要放置一头牛,因为分割后的四个2∗2的区域没有中心格子了。帮助约翰确定他需要在他的牧场里放置多少头牛。
输入格式:
一行,两个空格隔开的整数:N 和 M
输出格式:
需要的牛的只数
输入样例:
7 15
输出样例:
21
思路:
题目看起来挺复杂的,其实就是考察递归的知识。通过递归,将大问题化解为一个个小问题。
- 如果行列都是奇数
- 说明存在中间点,牛的数量+1
- 继续看划分出来的子区域,子区域的牛的数量要么是4*子区域的子区域的牛的数量,要么是4*0,所以直接+ 4*count(n/2, m/2)
- 如果行列不全是奇数
- 递归终止,牛在此区域的数量为0
参考代码:
#include<iostream>
using namespace std;
int count(int n, int m) {
if(n%2==0 || m%2==0) {
return 0;
} else {
return 1 + 4 * count(n / 2, m / 2);
}
}
int main() {
int n, m; cin>>n>>m;
cout<<count(n, m)<<endl;
return 0;
}