题目:
有 n 个硬币,一开始全部正面朝上,每次可以翻转 k 个硬币( k 小于 n ),那么至少要 p 次翻转,才能让所有硬币反面朝上,求 p 的值。如果不能成功翻转则输出-1
Input
输入2个数:n,k (1 <= n <= 10^9, 1 <= k <= 10^9)。
Output
输出翻转次数的最小值。 如果不能成功翻转则输出-1
Input示例
6 5
Output示例
6
在豆瓣的一个帖子里看到曾加老师的思路,就不把自己的拿出来丢人现眼了- -
附上按照这个思路写出来的代码:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n%2)
{
if(k%2==0)
{
printf("-1\n");
continue;
}
else
{
int f;
f=(n+k-1)/k;
if(f%2==0)
f++;
printf("%d\n",f);
continue;
}
}
else
{
if( (k%2==0)&&k>(n/2) && k<(n-1) )
{
printf("3\n");
continue;
}
else if( (k%2)&&k>(n/2) && k<=(n-1) )
{
int f;
f=(n+n-k-1)/(n-k);
if(f%2)
f++;
printf("%d\n",f);
continue;
}
else if( (k%2==0)&& k<=(n/2) )
{
int f;
f=(n+k-1)/k;
printf("%d\n",f);
continue;
}
else if( (k%2)&& k<=(n/2) )
{
int f;
f=(n+k-1)/k;
if(f%2)
f++;
printf("%d\n",f);
continue;
}
}
}
return 0;
}
然而我最开始想的和另一种想法一样,即:
求不定方程
xy=(2y+1)n
的最小正整数解。由简单的初等数论知识,这个方程有整数解的必要条件是k和2n的最大公约数也是n的约数,即不允许k是偶数而n是奇数的情况。在有解的情况下,这个方程可以用扩展欧几里得算法来解。
之后@ dogther 发现了一个bug,即:
翻转的次数不一定是n的倍数;
举个例子 n=7 k=3 的时候,1-7编号 ;
第一次翻转1-3,第二次翻转3-6;第三次翻转3和6和7即可;
于是不能翻转n的奇数倍来解决;
暂时我就卡在这里了,想到也许能通过二分图来实现,试一试,什么时候能写了再更
xy=(2y+1)n
的最小正整数解。由简单的初等数论知识,这个方程有整数解的必要条件是k和2n的最大公约数也是n的约数,即不允许k是偶数而n是奇数的情况。在有解的情况下,这个方程可以用扩展欧几里得算法来解。
之后@ dogther 发现了一个bug,即:
翻转的次数不一定是n的倍数;
举个例子 n=7 k=3 的时候,1-7编号 ;
第一次翻转1-3,第二次翻转3-6;第三次翻转3和6和7即可;
于是不能翻转n的奇数倍来解决;
暂时我就卡在这里了,想到也许能通过二分图来实现,试一试,什么时候能写了再更