• hdu 5791 Two 二维dp


    Two

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 889    Accepted Submission(s): 405


    Problem Description
    Alice gets two sequences A and B. A easy problem comes. How many pair of sequence A' and sequence B' are same. For example, {1,2} and {1,2} are same. {1,2,4} and {1,4,2} are not same. A' is a subsequence of A. B' is a subsequence of B. The subsequnce can be not continuous. For example, {1,1,2} has 7 subsequences {1},{1},{2},{1,1},{1,2},{1,2},{1,1,2}. The answer can be very large. Output the answer mod 1000000007.
     
    Input
    The input contains multiple test cases.

    For each test case, the first line cantains two integers N,M(1N,M1000). The next line contains N integers. The next line followed M integers. All integers are between 1 and 1000.
     
    Output
    For each test case, output the answer mod 1000000007.
     
    Sample Input
    3 2 1 2 3 2 1 3 2 1 2 3 1 2
     
    Sample Output
    2 3
     
    Author
    ZSTU
     
    Source
     题意:给你a,b两个数组,可以从a数组中按顺序选出一些数字,然后b数组按顺序选出一些数字,要求
    最后选出的数字按顺序相同,有多少选法。
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <algorithm>
    using namespace std;
    typedef  long long  ll;
    typedef unsigned long long ull;
    #define MM(a,b) memset(a,b,sizeof(a));
    #define inf 0x7f7f7f7f
    #define FOR(i,n) for(int i=1;i<=n;i++)
    #define CT continue;
    #define PF printf
    #define SC scanf
    const int mod=1000000007;
    const int N=1000+10;
    ull seed=13331;
    ll dp[N][N];
    int a[N],b[N];
    
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    
            MM(dp,0);
            for(int i=1;i<=n;i++)
               for(int j=1;j<=m;j++)
                       {
                           dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mod)%mod;
                           if(a[i]==b[j]) dp[i][j]=(dp[i][j]+dp[i-1][j-1]+1)%mod;
                       }
            printf("%lld
    ",dp[n][m]);
        }
        return 0;
    }
    

      分析:昨天比赛的时候一直想着怎么把暴力的复杂度降下去,想到了哈希,大数。。。就是将各种情况的对应到一个数值,,,,然并卵,,因为这道题目取的数字可以是不连续的,哈希跟大数就跪了。

    正确解法:设dp[i][j]为当前枚举到a是i位,b是j位的时候,那么先撇开(i,j)不看,那么

    dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];(注意dp[i-1][j-1]多算了一次

    如果a[i]==b[j],那么(i,j)还可以单独的产生组合,;

    最后要注意%mod时,两者相减可能会产生负数

    感觉取得数字要是不是连续的话一般就要上dp了

  • 相关阅读:
    公司后台切图
    XMLHttpRequest对象
    XML/JSDOM处理
    js访问xml之节点操作
    CSS3 输入框阴影效果及其他阴影效果
    GitHub用户仓库批量下载
    WTL10_9163应用向导安装后的小问题
    别学MFC了,要学就学这些...
    使用基于范围的 for 循环迭代范围
    使用未命名的命名空间代替静态全局变量
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5732319.html
Copyright © 2020-2023  润新知