zoukankan      html  css  js  c++  java
  • zoj3725 组合数学,递推

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3725

    题意:有n个格子,只能涂红、蓝两种颜色。要求至少有m个连续的格子涂上红色,求有多少种方法。

    思路:一开始是直接算,结果T了,不得不转变思想。要求至少m个格子连续的话,可以枚举连续m个格子的首位置。假如第i个格子开始往后的m个格子都是红色的,则后面的(n-(i+m)+1)个格子随意涂,有2^(n-(i+m)+1)种。此时第i-1个格子必然要为蓝色。且要求在前面的1到i-2个格子中不能有连续m个红格子。计前面i-2个格子有b[i]种放法。当i<m时,肯定不会出现连续m个红格子,所以随意放,b[i]= 2^i种放法。当i>=m时,b[i]=b[i-1]+b[i-2]+...+b[i-m],b[i+1]=2*b[i]=b[i-m],所以得到递推式b[i]=2*b[i-1]-b[i-m-1].当i-m-1<0时,b[i-m-1]=1.最后的话就用b[i-2]*a[n-m+1-i]求和就可以了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef  long long LL;
    const int maxn=100000+5;
    const int mod=1000000007;
    LL a[maxn],b[maxn];
    
    int main()
    {
        int n,m;
        LL ans;
        a[0]=1;
        for(int i=1; i<maxn; i++) a[i]=(a[i-1]*2)%mod;
        while(~scanf("%d%d",&n,&m))
        {
            ans=0;
            b[0]=1;
            for(int i=1; i<m; i++) b[i]=a[i];
            for(int i=m; i<=n; i++)
            {
                LL c;
                if(i-m-1>=0)
                    c=b[i-m-1];
                else c=1;
                b[i]=((2*b[i-1]-c)%mod+mod)%mod;
            }
            for(int i=1; i<=n-m+1; i++)
            {
                LL c;
                if(i==1) c=1;
                else c=b[i-2];
                ans=(ans+(c*a[n-m+1-i])%mod)%mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    DAY-4 Linux基础及常用命令(1)
    DAY-3 计算机基础之网络
    DAY-2 计算机基础之操作系统
    DAY-1 计算机基础
    梅花作品欣赏
    简洁大气网址(国外)跟设计大学的案例很像
    animate css3 应用的借鉴,一个同事写的JS
    漂亮的素材
    几个不错的素材站
    正式开始我的技术生涯
  • 原文地址:https://www.cnblogs.com/54zyq/p/3205135.html
Copyright © 2011-2022 走看看