理论解法转自知乎,原文链接:http://www.zhihu.com/question/26570175/answer/33312310
题目链接:http://www.51nod.com/contest/problem.html#!problemId=1613
【有 n 个硬币,一开始全部正面朝上,每次可以翻转 k 个硬币( k 小于 n ),那么至少要 p 次翻转,才能让所有硬币反面朝上,求 p 的值】
高能预警:
本题所用的数学工具不超过初中毕业水平,但情况繁多,完整讨论并不容易,结论写在最后。
解:
本题的精髓在于对奇偶性的讨论。
——情况1:若 n 为奇数——
1.1 若 k 为偶数 => 无解
证明:
若要让所有硬币最终翻面,则每个硬币都要翻面奇数次,共有奇数个硬币,所以所有硬币的翻面总数为奇数,但每次只能翻面偶数个硬币,显然不可能。证毕!
1.2 若 k 为奇数 => p为不小于 n/k 的最小奇数
(例1:n=7,k=5,那么 n/k =1.4 则 p=3 )
(例2:n=25,k=7,那么 n/k= 25/7 则 p=5)
证明:
必要性:
若要让所有硬币最终翻面,则每个硬币都要翻面奇数次,共有奇数个硬币,所以所有硬币的翻面总数为奇数,而每次只能翻奇数个硬币,所以总的翻转次数必然是奇数次,而翻转次数不到 n/k 次时,并不能使所有硬币至少翻面1次,所以p至少是不小于 n/k 的最小 奇数。
充分性:
- 当
时,只要3次翻转即可
第1次翻转编号:1~n-2
第2次翻转编号:1~n-3、n-1
第3次翻转编号:1~n-3、n
Done!(前 n-3 个硬币翻面 3 次,后 3 个翻面 1 次)
- 当
时,依然只要3次翻转
![\frac{3k-n}{2}](https://i-blog.csdnimg.cn/blog_migrate/cd111cc106181186427a81d55bf6edd6.png)
![\frac{3n-3k}{2}](https://i-blog.csdnimg.cn/blog_migrate/05c26c09a5dcc8cef7d4d7e5566da778.png)
- 当
时,需要p次翻转(p为不小于 n/k 的最小奇数)
![pk\geq n](https://i-blog.csdnimg.cn/blog_migrate/9f05367a3dfb1b8cffc12bc06eb08caf.png)
![(p-2)k<n](https://i-blog.csdnimg.cn/blog_migrate/353255341b73b63216cd4de17785029b.png)
![k<n](https://i-blog.csdnimg.cn/blog_migrate/563c5c00f24973834a2c827c5ea05d68.png)
![pk<3n](https://i-blog.csdnimg.cn/blog_migrate/3960e1f5ae88b8ec4617a14e7102e93f.png)
![\frac{pk-n}{2}](https://i-blog.csdnimg.cn/blog_migrate/9c909f868c6b760fe9eb20898c02f78a.png)
![\frac{3n-pk}{2}](https://i-blog.csdnimg.cn/blog_migrate/fe5a2a1b5d94f4c58dfe98eddbff4882.png)
——情况2:若 n 为偶数——
2.1 若
![\frac{n}{2}<k<n-1](https://i-blog.csdnimg.cn/blog_migrate/41400e2f2a89ac3ab0ac8f787bc1c773.png)
只要让前面的
![\frac{3k-n}{2}](https://i-blog.csdnimg.cn/blog_migrate/cd111cc106181186427a81d55bf6edd6.png)
![\frac{3n-3k}{2}](https://i-blog.csdnimg.cn/blog_migrate/05c26c09a5dcc8cef7d4d7e5566da778.png)
这个情况,和 n 为奇数是类似的。
2.2 若
这种情况比较特殊。
首先由奇偶性得出翻转次数必为偶数,而每一枚硬币翻转的次数为奇数,则每一枚硬币至少不翻转 1 次。
其次,每次有 n-k 枚不翻转,所以 p 必须不小于 n/(n-k) 。
方案:让前面
![\frac{kp-np+3n}{2}](https://i-blog.csdnimg.cn/blog_migrate/15a1a468b3496268cf03569e3a74c7ee.png)
![\frac{np-kp-n}{2}](https://i-blog.csdnimg.cn/blog_migrate/10949eec1e12787eb7a7993689187374.png)
2.3 若
当
![k=\frac{n}{2}](https://i-blog.csdnimg.cn/blog_migrate/d4e56f1c2744c9573d82ea2da61e7bff.png)
反之,只要让前面的
![\frac{pk-n}{2}](https://i-blog.csdnimg.cn/blog_migrate/9c909f868c6b760fe9eb20898c02f78a.png)
![\frac{3n-pk}{2}](https://i-blog.csdnimg.cn/blog_migrate/fe5a2a1b5d94f4c58dfe98eddbff4882.png)
2.4 若
当
![k=\frac{n}{2}](https://i-blog.csdnimg.cn/blog_migrate/d4e56f1c2744c9573d82ea2da61e7bff.png)
反之,首先由奇偶性得出翻转次数必为偶数,
只要让前面的
![\frac{pk-n}{2}](https://i-blog.csdnimg.cn/blog_migrate/9c909f868c6b760fe9eb20898c02f78a.png)
![\frac{3n-pk}{2}](https://i-blog.csdnimg.cn/blog_migrate/fe5a2a1b5d94f4c58dfe98eddbff4882.png)
————————————
综上所述:
若 n 为奇数:
- 若 k 为偶数
无解
- 若 k 为奇数
p 为不小于 n/k 的最小奇数
- 若 k为偶数,且
- 若 k为奇数,且
p 为不小于 n/(n-k) 的最小偶数
- 若 k为偶数,且
p 为不小于 n/k 的最小整数
- 若 k为奇数,且
p 为不小于 n/k 的最小偶数
// 翻硬币.cpp
#include <bits/stdc++.h>
#define LL long long
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define PI 3.1415926535897932626
#define EXIT exit(0);
#define PAUSE system("pause");
#define DEBUG puts("Here is a BUG");
#define SYNC_CLOSE ios::sync_with_stdio(false);
#define what_is(x) cout << #x << " is " << x << endl;
#define CLEAR(name, init) memset(name, init, sizeof(name));
const double eps = 1e-8;
const int MAXN = (int)1e9 + 5;
using namespace std;
int solve(int n, int k) {
if (n & 1) {
if (k & 1) {
int tmp = n/k + bool(n % k);
tmp += tmp % 2 == 0;
return tmp;
}
return -1;
}
if (k == n - 1) return n;
if (k*2 == n) return 2;
if (k % 2 == 0) {
if (k > n / 2) return 3;
return n/k + bool(n % k);
}
if (k > n / 2) {
k = n - k;
int tmp = n/k + bool(n % k);
tmp += tmp % 2;
return tmp;
}
int tmp = n/k + bool(n % k);
tmp += tmp % 2;
return tmp;
}
int main(int argc, char const *argv[]) {
#ifndef ONLINE_JUDGE
freopen("D:\\Documents\\Disk_Synchronous\\Programs\\Acm\\input.txt", "r", stdin);
#endif
int n, k;
cin >> n >> k;
cout << solve(n, k) << endl;
return 0;
}