zoukankan      html  css  js  c++  java
  • 小智的糖果(Candy) 51nod 提高组试题

    luogu AC通道! (官方数据)

    题目描述

    小智家里来了很多的朋友,总共有N个人,站成一排,分别编号为0到N-1,小智要给他们分糖果。但 是有的朋友有一些特殊的要求,有的人要求他左右的两个人(左边一个、右边一个,一共2个人)的 糖果数都比他的多,有的人要求他左右的两个人的糖果数都比他的少。同时小智希望给不同的人分到 的糖果数不相同,并且每个人至少有一个糖果,同时小智希望分出的糖果个数尽可能的少,现在小智 想知道有多少种分糖果的方法。数据保证不会出现两个人的要求产生冲突的情况。

    输入格式

    第一行三个数N,M,K,分别表示人数,第一种要求的人的个数,K表示第二种要求的人的个数。 接下来M行,每行一个数x,表示位置x的人要求他左右两个人的糖果数都比他的多 接下来K行,每行一个数y,表示位置y的人要求他左右两个人的糖果数都比他的少

    输出格式

    输出一个数表示方法数对 1000000007取模的结果。

    这道题考虑Dp解法。

    如何想到用DP解法?  因为题目中要求我们最多有多少种方法,如果一个个枚举或者求出的话,就会让我们的时间复杂度分分钟上去。因此这类题都是套路一般的DP。

    首先,看到题目中有两种要求。一种是让两边的小,一种是让两边的大。

    这种要求有一点不好处理的就是,我们总是喜欢直接查看每一个点的情况,而不是查看其旁边的点情况,这样很不方便。于是我们转换一下。

    设flagi = 1时,表示第 i 个点小于前一个点。同样的,当 flagi = 2时,表示第i个点大于前一个点。当然,falg = 0时,表示无特殊关系。

    然后,设置一个dp[i][j] 表示由前 i 个数组成的序列且第 i 位为 j 的合法情况数。在规划的过程中,针对不同的 flag[i],对应不同的状态转移,这里涉及到一个最后一位数 j 插入序列的思维,可以看做把前边的每一种排列中大于等于 j 的数 ++,也就可以达到空出 j 这个数将其插入的效果。

    在这里引入一个 sum[j],表示为前一轮状态下,最后一位小于等于 j 的情况的和。也就是说,当规划到第 i 位时,sum[j] 表示前 i - 1 位数组成的序列的合法情况的 dp[i - 1][j] 的前缀和。

    到这里,这道题也就可以被我们AC了。我们要求的和就是 sum[n].

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define N 100100
    #define isdigit(c) ((c)>='0'&&(c)<='9')
    const int mod = (int)1e9 + 7;
    
    inline int read(){
        int x = 0, s = 1;
        char c = getchar();
        while(!isdigit(c)){
            if(c == '-')s = -1;
            c = getchar();
        }
        while(isdigit(c)){
            x = (x << 1) + (x << 3) + (c ^ '0');
            c = getchar();
        }
        return x * s;
    }
    
    int flag[N], sum[N], dp[N];
    int main(){
    //    freopen("candy.in","r",stdin);
    //    freopen("candy.out","w",stdout);
        int n = read(), K = read(), M = read();
        for(int i = 1;i <= K; i++){
            int a = read();
            flag[++a] = 1;
            flag[a + 1] = 2;
        }
        for(int i = 1;i <= M; i++){
            int a = read();
            flag[++a] = 2;
            flag[a + 1] = 1;
        }
        dp[1] = sum[1] = 1;
        for(int i = 2;i <= n; i++){
            for(int j = 1;j <= i; j++){
                if(flag[i] == 0){
                    dp[j] = sum[i - 1] % mod;
                }
                else if(flag[i] == 1){
                    dp[j] = (sum[i - 1] - sum[j - 1] + mod) % mod;
                }
                else{
                    dp[j] = sum[j - 1];
                }
            }
            for(int j = 1;j <= i; j++){
                sum[j] = (sum[j - 1] + dp[j]) % mod;
            }
        }
        cout << sum[n] << endl;
        return 0;
    }
  • 相关阅读:
    spark 读取mongodb失败,报executor time out 和GC overhead limit exceeded 异常
    在zepplin 使用spark sql 查询mongodb的数据
    Unable to query from Mongodb from Zeppelin using spark
    spark 与zepplin 版本兼容
    kafka 新旧消费者的区别
    kafka 新生产者发送消息流程
    spark ui acl 不生效的问题分析
    python中if __name__ == '__main__': 的解析
    深入C++的new
    NSSplitView
  • 原文地址:https://www.cnblogs.com/wondering-world/p/12896710.html
Copyright © 2011-2022 走看看