原题连接spa
这是我本身Clone的专题,A,B题解昨天发过了.net
C:参考代码:code
/* 很容易咱们能够手推出n = 1, 2, 3时的状况,咱们假设前n - 1 列已经放好,方法有dp[n - 1]种,第n列很显然有1种方法,那我 再假设前n - 2列已经放好,方法有dp[n - 2]种,此时咱们知道 第n - 1和第n列确定是横着放的,若是他们竖着放就和前n - 1列 放好的状况相同,因此咱们能够推出方程dp[n] = dp[n - 1] + dp[n - 2]; */ #include <cstdio> using namespace std; typedef long long int ll; const int maxn = 50 + 5; int n; ll dp[maxn]; int main() { dp[1] = 1; dp[2] = 2; dp[3] = 3; for(int i = 4; i <= maxn; i ++) { dp[i] = dp[i - 1] + dp[i - 2]; } while(~scanf("%d", &n)) { printf("%lld\n", dp[n]); } return 0; }
D:参考代码:blog
/* 解题思路:仍是一如既往的递推...这个题和涂格子的那个题目很像 很容易咱们能够手推出n = 1, 2, 3的状况,对于第n个格子,我 们假设前n - 1个格子已经涂好了,那么咱们知道若是第n - 1个格子 是O,那么咱们第n个格子有两种涂法,若是不是O,咱们第n个格子有 三种涂法,对于第n - 1个格子,咱们能够看第n - 2个格子,若是 第n - 2个格子 */ #include <cstdio> using namespace std; typedef long long int ll; const int maxn = 40 + 5; int n; ll dp[maxn]; int main() { dp[1] = 3; dp[2] = 8; dp[3] = 22; for(int i = 4; i <= maxn; i ++) { dp[i] = 2 * (dp[i - 1] + dp[i - 2]); } while(~scanf("%d", &n)) { printf("%lld\n", dp[n]); } return 0; }
E:参考代码:get
/* 一样是递推,手推出n = 2, 3时全部未中奖的状况,咱们先把 他们抽奖假设为放东西,那么第n个参与者放东西时它能够放到 任意一个前面的位置即n - 1种方法,咱们假设为k为n放置的坐 标,那么咱们还须要将第k个放到其它位置,咱们知道当第k个放 到第n个位置时,其它n - 2个有dp[n - 2]种方法,当第k个不放 到第n个位置时,这n - 1个有dp[n - 1]种方法放置,因此咱们 能够得出dp[n] = (n - 1) * (dp[n - 1] + dp[n - 2])。 */ #include <cstdio> using namespace std; typedef long long int ll; const int maxn = 20 + 5; int c, n; ll dp[maxn]; ll mather[maxn]; int main() { dp[2] = 1; dp[3] = 2; mather[2] = 2; mather[3] = 6; for(int i = 4; i <= maxn; i ++) { dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]); mather[i] = mather[i - 1] * i; } scanf("%d", &c); while(c --) { scanf("%d", &n); printf("%.2f%%\n", ((double)dp[n] * 100) / mather[n]); } return 0; }
F:参考代码:io
/* 这个题多是上一题的增强版? 上一题是说n我的全为选中正确的百分比,这题是求n个里有m个全 未选中的种数,高中同窗应该都能想到选出m个让他们全不合格就行, C(n, m) * dp[m]即为方程了。 */ #include <cstdio> using namespace std; typedef long long int ll; const int maxn = 20 + 5; int c, n, m; ll dp[maxn], mather[maxn]; int main() { dp[2] = 1; dp[3] = 2; for(int i = 4; i <= maxn; i ++) dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]); scanf("%d", &c); while(c --) { scanf("%d %d", &n, &m); ll p = 1; for(int i = n - m + 1; i <= n; i ++) p *= i; for(int i = 1; i <= m; i ++) p /= i; printf("%lld\n", p * dp[m]); } return 0; }
G:参考代码:class
/* 这题一开始没有思路emm,去网上查了一下发现受益不浅。 参考直线相交,咱们发现每增长一条直线就会增长n - 1个交点, 就会增长n个平面,因此咱们知道对于直线相交产生的平面个数有 dp[n] = dp[n - 1] + n; 对于折线呢,咱们发现,每画一条折线咱们老是能和以前的n - 1 条折线多出4个交点,即总共多出4 * (n - 1) 个交点,那么就多出了 4 * (n - 1) + 1个面,就能够得出递推方程dp[n] = dp[n - 1] + 4 * [n - 1] + 1 对于Z型折线,画一画就能够知道每增长一条z型折线,最多能与原图的n - 1条z型折线 共多生成9 * (n - 1) 个交点,也便可以获得递推方程为 dp[n] = dp[n - 1] + 9 * (n - 1) + 1; */ #include <cstdio> using namespace std; typedef long long int ll; const int maxn = 10000 + 5; int c, n; ll dp[maxn]; int main() { dp[1] = 2; for(int i = 2; i <= maxn; i ++) { dp[i] = dp[i - 1] + 4 * (i - 1) + 1; } scanf("%d" ,&c); while(c --) { scanf("%d", &n); printf("%lld\n", dp[n]); } return 0; }