zoukankan      html  css  js  c++  java
  • HDU 2294 Pendant

    HDU_2294

        我们可以用f[i][j]表示珠子长度为i的时候一共有j种颜色的方案数,那么就有f[i][j]=j*f[i-1][j]+(K-j+1)*f[i-1][j-1],最后的结果就是f[1][K]+f[2][K]+…+f[N][K]。

        但由于N比较大,我们不能直接计算,但有了递推方程以后发现是可以构造出K*K的矩阵后用二分矩阵的方法去快速计算f[i][K]的,但对于f[1][K]+f[2][K]+…+f[N][K]这个表达式该如何求解呢?

        如果我们将构造出的递推关系的矩阵看成矩阵A,然后就可以用POJ_3233的方法先求A+A^2+A^3+…+A^K,然后就比较容易得到结果了。

        或者我们可以用g[i][j]表示珠子长度不超过i时一共有j种颜色的方案数,那么g[i][j]=g[i-1][j]+f[i][j],而最后结果就是g[N][K],这样我们也可以利用f[i][j]=j*f[i-1][j]+(K-j+1)*f[i-1][j-1]和g[i-1][j]=g[i-2][j]+f[i-1][j]这两个递推关系构造一个2K*2K的矩阵,然后二分这个矩阵直接求解,我的代码就是用这种方式写的。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 61
    #define D 1234567891
    int N, K, cnt;
    struct Matrix
    {
        long long a[MAXD][MAXD];
        void init()
        {
            int i;
            memset(a, 0, sizeof(a));
            for(i = 1; i < K; i ++)
                a[i][i] = K - i + 1, a[i][i + 1] = i;
            a[K][K] = 1;
            for(i = 1; i <= K; i ++)
                a[i + K][i + K] = 1, a[i + K][i] = 1;
        }
    }mat[150];
    int multiply(int x, int y)
    {
        int i, j, k, z = ++ cnt;
        long long ans;
        for(i = 1; i <= (K << 1); i ++)
            for(j = 1; j <= (K << 1); j ++)
            {
                ans = 0;
                for(k = 1; k <= (K << 1); k ++)
                    ans = (ans + mat[x].a[i][k] * mat[y].a[k][j]) % D;
                mat[z].a[i][j] = ans;
            }
        return z;
    }
    int powmod(int n)
    {
        int k;
        if(n == 1)
            return 0;
        k = powmod(n >> 1);
        k = multiply(k, k);
        if(n & 1)
            k = multiply(k, 0);
        return k;
    }
    void solve()
    {
        int k;
        scanf("%d%d", &N, &K);
        mat[0].init();
        cnt = 0;
        k = powmod(N - 1);
        printf("%I64d\n", (mat[k].a[1][K] * K + mat[k].a[K + 1][K] * K) % D);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            if(N == 1)
                printf("%d\n", K == 1 ? 1 : 0);
            else
                solve();
        }
        return 0;
    }
  • 相关阅读:
    ios获取iphone手机设备型号
    iOS项目中所有icon的尺寸以及命名
    c++达内视频
    ffmpeg教程
    FFMPEG SDK 教程
    minicom 下载
    线程同步的几种方法的总结
    多线程笔试面试概念问答
    buntu Rhythmbox解决中文乱码
    菜鸟学习ios
  • 原文地址:https://www.cnblogs.com/staginner/p/2470605.html
Copyright © 2011-2022 走看看