zoukankan      html  css  js  c++  java
  • 【u026】花园(garden)

    【问题描述】
    小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=1015)。他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<=M<=5,M<=N)个花圃中有不超过K(1<=K< M)个C形的花圃,其余花圃均为P形的花圃。
    例如,N=10,M=5,K=3。则
    CCPCPPPPCC 是一种不符合规则的花圃;
    CCPPPPCPCP 是一种符合规则的花圃。
    请帮小L求出符合规则的花园种数Mod 1000000007
    由于请您编写一个程序解决此题。

    【输入文件】
    一行,三个数N,M,K。
    【输出文件】
    花园种数Mod 1000000007

    【样例输入1】
    10 5 3
    【样例输出1】
    458

    【样例输入2】
    6 2 1
    【样例输出2】
    18

    【数据规模】
    40%的数据中,N<=20;
    60%的数据中,M=2;
    80%的数据中,N<=105。

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=u029

    【题解】

    先处理处1..m的情况,对于每个位置都有两个选择;
    和0..(2^m)-1的二进制一一对应;
    1的个数和1的个数对应;
    处理出1的个数小于等于k的状态;
    表示这些状态是可行的;
    然后考虑整体往右移动一位;
    然后获取了新的状态;

    [l..r]
    ->[l+1..r+1]
    这里枚举l..r的状态,然后对于新获取的状态;
    只有两种情况;
    r+1为0或者是r+1为1;
    如果新获取的状态1的个数小于等于k;
    则表示从l..r可以到达l+1..r+1;
    这个可以用位运算搞出来;
    (这个位运算自己推吧,看别人的程序挺可怕的..)
    然后就能获取出一个二维的矩阵了;
    求这个矩阵的(N-M)次幂;
    然后枚举初始的M个位置的状态,和末尾的M个位置的状态;
    看看练成环之后符不符合要求;
    符合要求的话就递增答案.
    这里矩阵乘法我写成函数的形式RE了。。。
    所以就没写成函数啦

    【完整代码】

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstdlib>
    #include <iostream>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%lld",&x)
    #define ref(x) scanf("%lf",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int N = 110;
    const int INF = 0x3f3f3f3f;
    const LL mod = 1000000007;
    
    struct juzhen
    {
        LL a[64][64];
        void init()
        {
            rep1(i,0,63)
                rep1(j,0,63)
                    a[i][j] = 0;
        }
    };
    
    int ma,num;
    LL ans = 0,n,rr[100],m,k;
    juzhen t,a;
    bool bo[64+10];
    
    void in()
    {
        cin >> n >> m >> k;
    }
    
    void pre()
    {
        ma = (1<<m)-1;
        rep1(i,0,ma)
        {
            int j = i,cnt = 0;
            while (j)
            {
                cnt+=(j&1);
                j>>=1;
            }
            if (cnt>k)
                bo[i] = false;
            else
                bo[i] = true;
        }
        t.init();
        rep1(i,0,ma)
        if (bo[i])
        {
            int te = ma-(1<<(m-1));
            te = i&te;
            te<<=1;
            t.a[i][te] = 1;
            if (bo[te+1])
                t.a[i][te+1] = 1;
        }
    }
    
    void special()
    {
        if (n==m)
        {
            int temp = 0;
            rep1(i,0,ma)
            if (bo[i])
                temp++;
            printf("%d
    ",temp);
            exit(0);
        }
    }
    
    void get_ksm()
    {
        LL tt = n-m;
        a.init();
        rep1(i,0,ma)
            rep1(j,0,ma)
                a.a[i][j] = t.a[i][j];
        while (tt)
        {
            if (tt==1) break;
            num++;
            rr[num] = tt&1;
            tt>>=1;
        }
       // exit(0);
        rep2(i,num,1)
        {
            //a = cheng(a,a);
            juzhen c;
            c.init();
            rep1(i,0,ma)
                rep1(j,0,ma)
                    rep1(k,0,ma)
                        c.a[i][j] = (c.a[i][j] + a.a[i][k]*a.a[k][j])%mod;
            rep1(i,0,ma)
                rep1(j,0,ma)
                    a.a[i][j] = c.a[i][j];
    
            if (rr[i]==1)
            {
                //a = cheng(a,t);
                juzhen c;
                c.init();
                rep1(i,0,ma)
                    rep1(j,0,ma)
                        rep1(k,0,ma)
                            c.a[i][j] = (c.a[i][j] + a.a[i][k]*t.a[k][j])%mod;
                rep1(i,0,ma)
                    rep1(j,0,ma)
                        a.a[i][j] = c.a[i][j];
            }
        }
    }
    
    void get_ans()
    {
        juzhen b;
        rep1(i,0,ma)
            if (bo[i])
            {
                b.init();
                b.a[0][i] = 1;
                //b = cheng(b,a);
    
                juzhen c;
                c.init();
                rep1(i,0,ma)
                    rep1(j,0,ma)
                        rep1(k,0,ma)
                            c.a[i][j] = (c.a[i][j] + b.a[i][k]*a.a[k][j])%mod;
                rep1(i,0,ma)
                    rep1(j,0,ma)
                        b.a[i][j] = c.a[i][j];
    
                rep1(j,0,ma)
                if (bo[j])
                {
                    bool ok = true;
                    LL t = j<<m;
                    t = t|i;
                    rep1(k,1,m-1)
                    {
                        int d = (1<<m)-1;
                        d = d<<(m-k);
                        d = d&t;
                        d>>=(m-k);
                        if (!bo[d])
                        {
                            ok = false;
                            break;
                        }
                    }
                    if (ok)
                        ans = (ans+b.a[0][j])%mod;
                }
            }
    }
    
    void o()
    {
        cout << ans << endl;
    }
    
    int main()
    {
        //freopen("D:\rush.txt","r",stdin);
        in();
        pre();
        special();
        get_ksm();
        get_ans();
        o();
        //printf("
    %.2lf sec 
    ", (double)clock() / CLOCKS_PER_SEC);
        return 0;
    }
    
    
  • 相关阅读:
    volley框架使用
    Insert Interval
    candy(贪心)
    Best Time to Buy and Sell Stock
    Best Time to Buy and Sell Stock III
    distinct subsequences
    edit distance(编辑距离,两个字符串之间相似性的问题)
    trapping rain water
    word break II(单词切分)
    sudoku solver(数独)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626521.html
Copyright © 2011-2022 走看看