传球游戏【NOIP2018普及组T3】(ybtoj 递推例题2)

题目描述

上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。

游戏规则是这样的: 个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没有传出去的那个同学就是败者,要给大家表演一个节目。

聪明的小蛮提出一个有趣的问题:有多少种不同的传球方法可以使得从小蛮手里开始传的球,传  次以后,又回到小蛮手里。两种传球方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有三个同学  号、 号、 号,并假设小蛮为  号,球传了  次回到小蛮手里的方式有  和 ,共  种。

输入格式

一行,有两个用空格隔开的整数 。

输出格式

 个整数,表示符合题意的方法数。

样例输入

3 3

样例输出

2

第一次写的时候,考虑f[i][j]为i个人传j次的合法方案数,当球来到第i个人手中时,球可能由周边(i - 1)个人传来,则推得f[i][j] = f[i - 1][j - 1] * (i - 1);
然后就写挂了。。。。。。

回来重新看题 发现是题没读懂。。
这是一个环 第i个人只能由左边或右边的人所指向 所以i的上一层应该是i - 1或i + 1,且环头环尾相接
所以 正确的递推式为 :
f[i][j] = f[i + 1][j - 1] + f[i - 1][j - 1];
注意!!:
当遇到环头或环尾时 需要特判:
当传到第一个人时 第一个人会由第二个人或第n个人传来
当传到第n个人时 第n个人会由第n - 1个人或第一个人传来
特判完成 上代码!!!
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <climits>
 5 #include <cassert>
 6 #include <cmath>
 7 #include <cstring>
 8 #include <cstdlib>
 9 #include <cctype>
10 #include <utility>
11 #include <set>
12 #include <map>
13 #include <stack>
14 #include <queue>
15 #include <vector>
16 #define int long long
17 #define ll long long
18 #define ull unsigned long long
19 #define re register
20 #define lowbit(x) x & (-x)
21 #define gcd(a,b) _gcd(a,b)
22 #define mid ((l + r) >> 1)
23 #define rep(i,a,b)  for(re int i(a);i <= b;i ++)
24 #define rrep(i,a,b) for(re int i(a);i >= b;i --)
25 using namespace std;
26 inline int read(){
27     re int x = 0,f = 1;
28     re char ch = getchar();
29     while(ch < '0' || ch > '9'){
30         if(ch == '-') f = -1;
31         ch = getchar();
32     }
33     while(ch >= '0' && ch <= '9'){
34         x = (x << 3) + (x << 1) + (ch ^ 48);
35         ch = getchar();
36     }
37     return x * f;
38 }
39 int f[301][301];
40 signed main(){
41     int n = read();
42     int k = read();
43     f[1][0] = 1;
44     rep(i,1,k){
45         rep(j,1,n){
46             if(j == 1) f[j][i] = f[2][i - 1] + f[n][i - 1];
47             else
48             if(j == n) f[j][i] = f[1][i - 1] + f[n - 1][i - 1];
49             else f[j][i] = f[j - 1][i - 1] + f[j + 1][i - 1];
50         }
51     }
52     cout << f[1][k] << endl;
53     return 0;
54 }

国赛神犇加油!!

24OIfighting!!!

 
posted @ 2022-08-20 11:08  November&&Rain  阅读(92)  评论(0)    收藏  举报