• 0x5C 计数类DP


    cf 559C 考虑到黑色的格子很少,那么我把(1,1)变成黑色,然后按每个黑色格子接近终点的程度排序,计算黑色格子不经过另一个黑色格子到达终点的方案,对于当前的格子,要减去在它右下角的所有方案数(注意不是f值)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    LL MOD(LL x){return (x%mod+mod)%mod;}
    
    LL jc[310000],inv[310000];
    LL quick_pow(LL A,LL p)
    {
        LL ret=1;
        while(p!=0)
        {
            if(p%2==1)ret=(ret*A)%mod;
            A=(A*A)%mod;p/=2;
        }
        return ret;
    }
    LL getC(int n,int m){return jc[m]*inv[m-n]%mod*inv[n]%mod;}
    
    struct node{int x,y;}a[2100];
    bool cmp(node n1,node n2){return n1.x+n1.y>n2.x+n2.y;}
    LL f[2100];
    int main()
    {
        jc[0]=1,inv[0]=1;for(int i=1;i<=300000;i++)jc[i]=(jc[i-1]*i)%mod,inv[i]=quick_pow(jc[i],mod-2);
        int n,m,K;
        scanf("%d%d%d",&n,&m,&K);
        for(int i=1;i<=K;i++)
            scanf("%d%d",&a[i].x,&a[i].y);
        a[++K].x=1,a[K].y=1;
        sort(a+1,a+K+1,cmp);
        
        for(int i=1;i<=K;i++)
        {
            f[i]=getC(n-a[i].x,(n+m)-(a[i].x+a[i].y));
            for(int j=1;j<i;j++)
                if(a[i].x<=a[j].x&&a[i].y<=a[j].y)
                {
                    f[i]=MOD( f[i]-MOD(f[j]*getC(a[j].x-a[i].x,(a[j].x+a[j].y)-(a[i].x+a[i].y))) );
                }
        }
        printf("%I64d
    ",f[K]);
        return 0;
    }
    cf 559C

    poj1737 口胡一波题解,我们知道n个点的无向图个数有2^(n*(n-1)/2)个,那么就去算不联通的,假设存在有一个包括点1的块大小为k,剩下的就是n-k个点的无向图个数了。

    poj1037 其实可以借鉴一下康托展开的思想的。。。对于当前位应该选取最大的那个剩下位方案数少于m的,那么方案数就要用DP维护了。设f[i][j][k]表示枚举到第几位,选的是当前排第j的,是高位还是低位。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    LL f[30][30][2];
    
    void initf()
    {
        f[1][1][0]=f[1][1][1]=1;
        for(int i=2;i<=20;i++)
            for(int j=1;j<=i;j++)
            {
                for(int k=j;k<=i-1;k++)f[i][j][0]+=f[i-1][k][1];
                for(int k=1;k<=j-1;k++)f[i][j][1]+=f[i-1][k][0];
            }
    }
    
    bool v[30];
    int main()
    {
        initf();
        
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n;LL m;
            scanf("%d%lld",&n,&m);
            memset(v,false,sizeof(v));
            int x,k;
            for(int j=1;j<=n;j++)
            {
                if(f[n][j][1]>=m){x=j,k=1;break;}
                else m-=f[n][j][1];
                
                if(f[n][j][0]>=m){x=j,k=0;break;}
                else m-=f[n][j][0];
            }
            v[x]=true;printf("%d",x);
            for(int i=2;i<=n;i++)
            {
                k^=1; int j=0;
                for(int y=1;y<=n;y++)
                {
                    if(v[y]==true)continue;
                    j++;
                    
                    if((k==0&&y<x)||(k==1&&y>x))
                    {
                        if(f[n-i+1][j][k]>=m){x=y;break;}
                        else m-=f[n-i+1][j][k];
                    }
                }
                v[x]=true;printf(" %d",x);
            }
            printf("
    ");
        }
        return 0;
    }
    poj1037
  • 相关阅读:
    洛谷P3620 [APIO/CTSC 2007] 数据备份
    洛谷P2744 量取牛奶
    洛谷P1560 蜗牛的旅行
    luogu P1776 宝物筛选_NOI导刊2010提高(02)
    luogu P1020 导弹拦截
    luogu P2015 二叉苹果树
    luogu P1137 旅行计划
    树形dp瞎讲+树形dp基础题题解
    luogu P1252 马拉松接力赛 P1803 凌乱的yyy / 线段覆盖
    luogu P1196 [NOI2002]银河英雄传说
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9482187.html
Copyright © 2020-2023  润新知