zoukankan      html  css  js  c++  java
  • [Sdoi2010]地精部落

    1925: [Sdoi2010]地精部落

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1300  Solved: 800
    [Submit][Status][Discuss]

    Description

    传说很久以前,大地上居住着一种神秘的生物:地精。 地精喜欢住在连绵不绝的山脉中。具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到N 之间的正 整数。 如果一段山脉比所有与它相邻的山脉都高,则这段山脉是一个山峰。位于边 缘的山脉只有一段相邻的山脉,其他都有两段(即左边和右边)。 类似地,如果一段山脉比所有它相邻的山脉都低,则这段山脉是一个山谷。 地精们有一个共同的爱好——饮酒,酒馆可以设立在山谷之中。地精的酒馆 不论白天黑夜总是人声鼎沸,地精美酒的香味可以飘到方圆数里的地方。 地精还是一种非常警觉的生物,他们在每座山峰上都可以设立瞭望台,并轮 流担当瞭望工作,以确保在第一时间得知外敌的入侵。 地精们希望这N 段山脉每段都可以修建瞭望台或酒馆的其中之一,只有满足 这个条件的整座山脉才可能有地精居住。 现在你希望知道,长度为N 的可能有地精居住的山脉有多少种。两座山脉A 和B不同当且仅当存在一个 i,使得 Ai≠Bi。由于这个数目可能很大,你只对它 除以P的余数感兴趣。

    Input

    仅含一行,两个正整数 N, P。

    Output

    仅含一行,一个非负整数,表示你所求的答案对P取余 之后的结果。

    Sample Input

    4 7

    Sample Output

    3

    HINT


     
    对于 20%的数据,满足 N≤10; 
    对于 40%的数据,满足 N≤18; 
    对于 70%的数据,满足 N≤550; 
    对于 100%的数据,满足 3≤N≤4200,P≤109

    Source

    第一轮Day2

    /*
    Orz 魏铭。
    想出来满分做法。。但是只能70分。
    首先,设状态f[i][H][0/1]表示序列posi是H,且为山峰/山谷。然后转移很显然。
    不过实现只能强打记忆化搜索。为什么呢?因为他是一个排列。转递推就要状压。就是用bitset也会爆。
    抛开空间不讲。时间也过不了。
    为什么?转移时O(n)的。如何优化?用前缀和优化变为O(1)。
    在处理好空间且保证状态正确的前提下,转成递推,用前缀和转移就好了。当时也想到了,但,写不出来。
    当场 魏铭 就用一种很神奇的方法,解决了我的问题,然,我还是看不懂。码力太弱了。。。
    此题对我感触很大。
    思维:从裸暴力->状压剪枝->换状态->换状态->换状态->优化->正解思路≠>正解代码(码力弱)。
    */
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define set(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
    using namespace std;
    typedef long long ll;
    const int N=555;
    int n,vis[N];
    ll f[N][N][2];
    ll ans,mod;
    //d=1 high
    //d=0 low
    ll dfs(int cur,int h,bool d){
        ll &res=f[cur][h][d];
        if(~res) return res;
        res=0;
        if(cur>=n) return res=1; 
        if(d){
            for(int i=1;i<h;i++){
                if(!vis[i]){
                    vis[i]=1;
                    res+=dfs(cur+1,i,!d);
                    vis[i]=0;
                }
            }
        }
        else{
            for(int i=h+1;i<=n;i++){
                if(!vis[i]){
                    vis[i]=1;
                    res+=dfs(cur+1,i,!d);
                    vis[i]=0;
                }
            }
        }
        return res%=mod;
    }
    inline void DFS(){
        for(int i=1;i<=n;i++){
            vis[i]=1;
            dfs(1,i,0);
            dfs(1,i,1);
            vis[i]=0;
        }
        for(int i=1;i<=n;i++){
            ans=(ans+f[1][i][0]+f[1][i][1])%mod;
        }
    }
    int main(){
        set(goblin);
        memset(f,-1,sizeof f);
        scanf("%d%I64d",&n,&mod);
        if(n==1){printf("%I64d",1LL%mod);}
        if(mod==1){printf("0");}
        DFS();
        printf("%I64d",ans);
        return 0;
    } 
    /*
    附魏铭100分代码
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    #define zbwmqlw
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define abs(x) ((x)>0?(x):-(x))
    #define pow(x) (1<<(x))
    const int inf=0x3f3f3f3f;
    typedef __int64 LL;
    template<class T> void checkmin(T &a,const T &b) 
    {if (b<a) a=b;}
    template<class T> void checkmax(T &a,const T &b)
    {if (b>a) a=b;}
    
    const int N=4300;
    int a[20];
    bool vis[20],now,last;
    int n,ans;
    LL f[2][N][2],mo;
    
    void dfs(int depth)
    {
        if (depth==n+1) {
            ++ans;
            return;
        }
        int i;
        for (i=1;i<=n;++i) if (!vis[i]) {
            a[depth]=i;
            if (depth>2 && (a[depth]>a[depth-1])==(a[depth-1]>a[depth-2])) continue;
            vis[i]=true;
            dfs(depth+1);
            vis[i]=false;
        }
    }
    
    void solvedfs()
    {
        ans=0;
        dfs(1);
        printf("%d %d
    ",n,ans);
        exit(0);
    }
    
    void solvedp()
    {
        int i,j,k;
        now=true; last=false;
        memset(f[now],0,sizeof(f[now]));
        for (j=0;j<n;++j) f[now][j][0]=f[now][j][1]=1;
        for (i=2;i<=n;++i) {
            now^=1; last^=1;
            memset(f[now],0,sizeof(f[now]));
            LL s0=0,s1=0;
            for (k=0;k+i-1<=n;++k) s1+=f[last][k][1];
            for (j=0;j+i<=n;++j) {
                s0+=f[last][j][0];
                s1-=f[last][j][1];
                f[now][j][1]=s0%mo;
                f[now][j][0]=s1%mo;
            }
        }
        printf("%I64d
    ",(f[now][0][0]+f[now][0][1])%mo);
    }
    
    int main()
    {
        freopen("goblin.in","r",stdin);
        freopen("goblin.out","w",stdout);
        scanf("%d%I64d",&n,&mo);
        solvedp();
        fclose(stdout);
    }
    
    */
    70分心痛代码

    AC思路:http://blog.csdn.net/mrazer/article/details/53426415?locationNum=12&fps=1

    #include<cstdio>
    #define set(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
    using namespace std;
    const int N=4201;
    int f[2][N],n,now,mod,ans;
    int main(){
        set(goblin);
        scanf("%d%d",&n,&mod);
        f[now][1]=1;
        for(int i=2;i<=n;i++){
            now^=1;
            for(int j=1;j<=i;j++){
                f[now][j]=(f[now][j-1]+f[now^1][i-j+1])%mod;
            }
        }
        for(int i=1;i<=n;i++) ans=(ans+f[now][i])%mod;
        printf("%d
    ",ans*2%mod);
        return 0;
    }
  • 相关阅读:
    jmeter压测-05-xpath表达式
    测试那些事-测试资源篇
    测试那些事-沟通篇
    测试那些事-前端
    测试那些事儿-后端
    记一次大数据量不同处理方式下服务器负载
    jmeter压测dubbo接口,参数为dto时如何写传参及有错误时的分析思路
    pyton3 字典排序
    python测试dubbo接口
    记录一下telnet测试dubbo接口,参数为dto时怎么测试,枚举类型传参
  • 原文地址:https://www.cnblogs.com/shenben/p/6613695.html
Copyright © 2011-2022 走看看