zoukankan      html  css  js  c++  java
  • 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了

  • 相关阅读:
    JavaScript Date对象和函数 (一)
    Css3 文字渐变整理(一)
    Asp.net Core CacheHelper 通用缓存帮助类
    .net core中使用GB2312编码的问题
    苹果手机微信浏览器select标签选择完成之后页面不会自动回到原位
    .Net Core NOPI操作word(二) 表格操作
    .Net Core NOPI操作word(一)
    .NetCore中EFCore的使用整理(三)-关联表操作
    windos server2012安装.net core 2.2问题
    C# 最简单的使程序单进程运行的方法
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5732319.html
Copyright © 2011-2022 走看看