Codeforces Round #230 (Div. 1)B,C

来源:互联网 发布:葡萄牙 法国 知乎 编辑:程序博客网 时间:2024/06/11 22:01

B.汉诺塔问题原型就是用递归解的,这里加上了每步的费用,无非是 递归+dp一下,也就是记忆化dp就可以了

注意long long

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <iostream>using namespace std;typedef long long ll;int t[4][4];const ll inf = 1e18;typedef long long ll;ll dp[4][4][55];ll dfs(int a, int b, int n) {int c = 3^a^b;if(n == 1) return min(t[a][c] + t[c][b], t[a][b]);if(dp[a][b][n] != -1) return dp[a][b][n];ll &ret = dp[a][b][n];ret = inf;ret = min(ret, t[a][b] + dfs(a, c, n-1) + dfs(c, b, n-1));ret = min(ret, t[a][c]+t[c][b] + dfs(a, b, n-1)*2+dfs(b, a, n-1));return ret;}int main() {int i, j, n;for(i = 0; i < 3; i++)for(j = 0; j < 3; j++)scanf("%d", &t[i][j]);scanf("%d", &n);memset(dp, -1, sizeof(dp));cout << dfs(0, 2, n) << endl;return 0;}


C.比较重口味的矩阵乘法,类型很容易看出来, 以前做过1^k+2^k+.......n^k, 现在加了斐波那契系数, 我们需要知道如何从Fi*i^k通过构造一个矩阵推出Fi+1 * (i+1)^k ,  这里系数和底数都发生了改变,  我们只能一步一步做改变,  用组合数 把 i^k变成(i+1)^k,然后用斐波那契公式把 Fi 变成Fi+1,所以矩阵大小扩大了两倍,  大小为2*k+3

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;typedef long long ll;const int N = 84;ll a[N][N], e[N][N];ll t;int k, n;const ll mod = 1e9 + 7;void mult(ll a[N][N], ll b[N][N]) {    ll c[N][N] = { 0 };    int i, j, k;    for(i = 0; i < n; i++)        for(j = 0; j < n; j++)            if(a[i][j]) for(k = 0; k < n; k++) {                c[i][k] +=  a[i][j] * b[j][k] % mod;                c[i][k] %= mod;            }    for(i = 0; i < n; i++)        for(j = 0; j < n; j++)            a[i][j] = c[i][j];}ll C[N][N];ll tp[N];int main() {    int i, j;    for(i = 0; i < N; i++) {        C[i][0] = C[i][i] = 1;        for(j = 1; j < i; j++)            C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;    }    cin >> t >> k;    n = k * 2 + 3;    if(t == 1) {        puts("1");        return 0;    }    t--;    //**********tp    tp[k] = 2;    for(i = k-1; i >= 0; i--)        tp[i] = tp[i+1]*2%mod;    tp[n-1] = tp[n-2] = 1;    for(i = n-3; i > k; i--)        tp[i] = tp[i+1]*2%mod;    //*************e    for(i = 0; i < n; i++)        for(j = 0; j < n; j++)            e[i][j] = (i == j);    //*************a    for(i = 0; i <= k; i++)        for(j = i; j <= k; j++)            a[j][i] = a[j + k + 1][i] =                    a[j][i + k + 1] = C[k - i][k - j];    a[0][n - 1] = a[n - 1][n - 1] = 1;    //*******pow    while (t > 0) {        if(t & 1) mult(e, a);        mult(a, a);        t >>= 1;    }    ll ans = 0;    for(i = 0; i < n; i++) {        ans += tp[i] * e[i][n - 1] % mod;        ans %= mod;    }    cout << ans << endl;    return 0;}


3 0
原创粉丝点击