D-地虎侠
1
1
1堆石子有
n
n
n个,两人轮流取.先取者第
1
1
1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的
2
2
2倍。取完者胜.先取者负输出"
S
e
c
o
n
d
Second
Second
w
i
n
win
win“.先取者胜输出”
F
i
r
s
t
First
First
w
i
n
win
win“.
I
n
p
u
t
Input
Input
输入有多组.每组第
1
1
1行是
2
<
=
n
<
2
31
2<=n<2^{31}
2<=n<231,
n
=
0
n=0
n=0退出.
O
u
t
p
u
t
Output
Output
先取者负输出”
S
e
c
o
n
d
Second
Second
w
i
n
win
win“. 先取者胜输出”
F
i
r
s
t
First
First
w
i
n
win
win".
S
a
m
p
l
e
I
n
p
u
t
Sample Input
SampleInput
2
2
2
13
13
13
10000
10000
10000
0
0
0
S
a
m
p
l
e
O
u
t
p
u
t
Sample Output
SampleOutput
S
e
c
o
n
d
w
i
n
Second win
Secondwin
S
e
c
o
n
d
w
i
n
Second win
Secondwin
F
i
r
s
t
w
i
n
First win
Firstwin
首先全文无干货,全是瞎几把写,想看干货可以移步斐波那契博弈
题目分析:想了几分钟没思路,也许是规律题,直接开始打表(遇事不决先打表?)
n | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
\ | S | S | F | S | F | F | S |
这里
F
F
F 表示先手胜利,
S
S
S 表示后手胜利。
刚开始看没有什么规律,感觉就是乱赢的…之后注意到后手
(
S
)
(S)
(S)赢时
n
n
n似乎满足斐波那契数列
(
2
,
3
,
5
,
8
)
(2,3,5,8)
(2,3,5,8)然后为了验证继续打表到
13
13
13。
9 | 10 | 11 | 12 | 13 |
---|---|---|---|---|
F | F | F | F | S |
搏一搏单车变摩托…然后就一发
A
C
AC
AC了
贴一下我 A C AC AC的代码:(脑抽一开始写斐波那契数列就顺手写矩阵快速幂模板,后面懒得改了)
#include<stdio.h>
#include<string.h>
struct Mat {
long long mat[3][3];
};
Mat Mult(Mat A, Mat B) {
Mat ans1;
memset(ans1.mat, 0, sizeof ans1.mat);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
ans1.mat[i][j] += (A.mat[i][k] * B.mat[k][j]);
ans1.mat[i][j];
}
}
}
return ans1;
}
Mat Pow(Mat A, int n) {
Mat ans2;
memset(ans2.mat, 0, sizeof ans2.mat);
for (int i = 0; i < 2; i++)
ans2.mat[i][i] = 1;
while (n) {
if (n % 2)
ans2 = Mult(ans2, A);
A = Mult(A, A);
n /= 2;
}
return ans2;
}
int main() {
long long n, num, x = 0, y = 1;
while (scanf("%lld", &n) != EOF) {
if (n == 0)
break;
int i, a = 1;
Mat ans;
for (i = 2; i <= 50; i++) { //2^31=2147483647 斐波那契数列在第47项就已经超过这个数了
ans.mat[0][0] = 1;
ans.mat[0][1] = 1;
ans.mat[1][0] = 1;
ans.mat[1][1] = 0;
ans = Pow(ans, i - 1);
num = ans.mat[0][0] * y + ans.mat[0][1] * x;
if (num == n) {
printf("Second win\n");
a = 0;
}
}
if (a)
printf("First win\n");
}
return 0;
}
其实直接打斐波那契数列表,然后一一对应就好了。
#include<stdio.h>
int main()
{
long long i,n,a[50];
a[0]=0;a[1]=1;
for(i=2;i<=48;i++)
a[i]=a[i-1]+a[i-2];
while(scanf("%lld",&n),n){
int flag=1;
for(i=2;i<=48;i++){
if(n==a[i]){
printf("Second win\n");
flag=0;
}
}
if(flag)
printf("First win\n");
}
return 0;
}
恭喜 F L S FLS FLS让我喜提一篇博客。。