题目描述
有 n 个硬币,一开始全部正面朝上,每次可以翻转 k 个硬币( k 小于 n ),那么至少要 p 次翻转,才能让所有硬币反面朝上,求 p 的值。如果不能成功翻转则输出-1
数据范围
n,k (1 <= n <= 10^9, 1 <= k <= 10^9)。
看数据范围就知道,复杂度应该为O(1)
本题的精髓在于对奇偶性的讨论。
情况1:若 n 为奇数——
1.1 若 k 为偶数 => 无解
证明:
若要让所有硬币最终翻面,则每个硬币都要翻面奇数次,共有奇数个硬币,所以所有硬币的翻面总数为奇数,但每次只能翻面偶数个硬币,显然不可能。证毕!
1.2 若 k 为奇数 => p为不小于 n/k 的最小奇数
证明:
若要让所有硬币最终翻面,则每个硬币都要翻面奇数次,共有奇数个硬币,所以所有硬币的翻面总数为奇数,而每次只能翻奇数个硬币,所以总的翻转次数必然是奇数次,而翻转次数不到 n/k 次时,并不能使所有硬币至少翻面1次,所以p至少是不小于 n/k 的最小奇数。而p为奇数,k为奇数,所以总次数为奇数,而且我们保证了所有硬币至少翻了一次,同时可以保证所有硬币的翻转次数为奇数,所以p为不小于 n/k 的最小奇数是能保证有解的,且p就是最小解。
情况2:若 n 为偶数——
2.0若k=n-1,p=n
2.1 若
n/2<k<n−1
且为偶数=> p=3
这个情况,和 n 为奇数是类似的。
2.2 若
n/2<k<n−1
且为奇数=>p=4
这种情况比较特殊。
首先由奇偶性得出翻转次数必为偶数,而每一枚硬币翻转的次数为奇数,则每一枚硬币至少不翻转 1 次。
其次,每次有 n-k 枚不翻转,所以 p 必须不小于 n/(n-k) 。
2.3 若k<=n/2且为偶数=> p为不小于 n/k 的最小整数,显然
2.4 若k<=n/2且为奇数=> p为不小于 n/k 的最小偶数
首先由奇偶性得出翻转次数必为偶数,同理可得。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
int n,k,p;
scanf("%d%d",&n,&k);
p=n/k;
if (n%k!=0) p++;
if (n%2==1){
if (k%2==0) printf("-1");else{
if (p%2==0) p++;
printf("%d\n",p);
}
}else{
int n1=n/2;
if (k%2==0){
if (k>n1) printf("3");else printf("%d\n",p);
}else{
int p1=n/(n-k);
if (n%(n-k)!=0) p1++;
if (k>n1) printf("%d\n",p1);else {
if (p%2==1) p++;
printf("%d\n",p);
}
}
}
}