<每日一題> Day6:HDU遞推專題完結

原題連接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;
}
相關文章
相關標籤/搜索