zoukankan      html  css  js  c++  java
  • Choosing number ZOJ 3690 (矩阵快速幂)

    题意:n个人站成一排,每个人任意从1——m中任意取一个数,要求相邻两个人的如果数字相同,数字要大于k。

    分划思想推导表达式:

    假设  i  个人时。第i个人的选择有两种一种是选择小于等于k的数,另一种是大于k的数。则设这两种情况的组合数分别为F(i)和 G(i)

    那么F(i)=(m-k)(F(i-1)+G(i-1));m-k表示第i个人,选择了大于k的选择。

    那么G(i)=kF(i-1)+(k-1)G(i-1);  k*F(i-1),表示第i个人选的是大于k的数,而第i个人只能在0—k种选择,所以0—k都可以选择。但是,如果第i-1人选择了

    0—k中的一个数,那么为了满足条件相邻元素大于k的原则,所以不能选择第i-1的数,所以是k-1;

    然后就是基础的构造函数了。

    #include<cstdio>
    #include<cstring>
    #define mod int(1e9+7)
    #define ll long long
    ll m, k, n;
    struct jz
    {
        ll num[2][2];
        jz(){ memset(num, 0, sizeof(num)); }
        jz operator*(const jz &p)const
        {
            jz ans;
            for (int k = 0; k < 2;++k)
            for (int i = 0; i < 2;++i)
            for (int j = 0; j < 2; ++j)
                ans.num[i][j] = (ans.num[i][j] + num[i][k] * p.num[k][j] % mod) % mod;
            return ans;
        }
    }p;
    jz POW(jz x, ll n)
    {
        jz ans;
        for (int i = 0; i < 2; ++i)ans.num[i][i] = 1;
        for (; n;n>>=1, x=x*x)
        if (n & 1)ans = ans*x;
        return ans;
    }
    void init()
    {
            p.num[0][0] = m - k; p.num[0][1] = m - k;
            p.num[1][0] = k; p.num[1][1] = k - 1;
    }
    int main()
    {
        while (scanf("%lld%lld%lld", &n, &m, &k)!=EOF)
        {
            ll G1 = k;
            ll F1 = m - k;
                init();
                jz ans = POW(p, n - 1);
                printf("%lld\n", (ans.num[0][0] * F1%mod + ans.num[0][1] * G1%mod+ans.num[1][0]*F1%mod+ans.num[1][1]*G1%mod) % mod);
        }
        return 0;
    }
  • 相关阅读:
    thrift python安装
    第二周习题F
    Equivalent Strings
    生成可重集的排列(方法)
    分数拆分(刘汝佳紫书P183)
    Prime ring problem
    Maximun product
    Division
    每周一赛(E题,广搜求方案)
    ICE CAVE(BFS搜索(模拟))
  • 原文地址:https://www.cnblogs.com/ALINGMAOMAO/p/9502179.html
Copyright © 2011-2022 走看看