• 小a和uim之大逃离(luogu P1373 dp)


    小a和uim之大逃离(luogu P1373 dp)

    给你一个n*m的矩阵,其中元素的值在1~k内。限制只能往下和往右走,问从任意点出发,到任意点结束,且经过了偶数个元素的合法路径有多少个。在此题中,定义在一条路径中,第奇数个元素之和为X,第偶数个元素之和为Y。X+Y同模k+1的路径是合法路径。答案模1e9+7。n,m<=800,1<=k<=15。

    状态是(f[i][j][h][0/1]),表示第i行第j列的元素,奇数元素和X-偶数元素和Y差为h,当前在路径中是第奇数个点或第偶数个点的方案数。

    (p1=(p-a[j]+k+1)\% (k+1))(p2=(p+a[j])\%(k+1))。那么状态转移方程就是:$$f[i][j][p][0]=f[i][j-1][p1][1]+f[i-1][j][p1][1]+(p1?0:1)$$$$f[i][j][p][1]=f[i][j-1][p2][0]+f[i-1][j][p2][0]$$

    状压一下即可。

    #include <cctype>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int mod=1e9+7;
    const int maxn=805, maxk=20;
    typedef int ia3[maxn][maxk][2];
    int n, m, k, ans, a[maxn];
    ia3 fnow, fpre;
    
    void getint(int &x){
        char ch; int flag=1; x=0;
        for (ch=getchar(); !isdigit(ch); ch=getchar())
            if (ch=='-') flag=-1;
        for (x=ch-48; ch=getchar(), isdigit(ch);)
            x=x*10+ch-48;
        x*=flag;
    }
    
    int main(){
        scanf("%d%d%d", &n, &m, &k);
        int p1, p2;
        for (int i=1; i<=n; ++i)
            for (int j=1; j<=m; ++j){
                getint(a[j]);
                for (int p=0; p<=k; ++p){
                    p1=(p-a[j]+k+1)%(k+1); //这一步若小A走
                    p2=(p+a[j])%(k+1); //这一步若uim走
                    fnow[j][p][0]=(fnow[j-1][p1][1]
                            +fpre[j][p1][1]+(p1?0:1))%mod;
                    fnow[j][p][1]=(fnow[j-1][p2][0]
                            +fpre[j][p2][0])%mod;
                    if (p==0) ans=(ans+fnow[j][p][1])%mod;
                }
                memcpy(fpre[j], fnow[j], sizeof(fnow[j]));
            }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    递归实现全排列问题
    LeetCode
    LeetCode
    连续子元素最大和
    简单模板view调用
    如何清除PHP中不需要的Layout模板
    Model中设置表单验证方法
    数据修改操作
    MVC模式tp框架四中路由形式
    zend Framework的MVC模式的搭建
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/8028409.html
Copyright © 2020-2023  润新知