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了

  • 相关阅读:
    linux——03-DevOps实战(详版)
    总结跟语言无关的东西
    drf—— RBAC-基于角色的访问控制
    drf—— 全局异常
    122买卖股票的最佳时机
    还记得这门古老的编程语言么,送你一份perl书单!
    程序员学习必备书单汇总,超全!
    书单来了!大厂的技术牛人在读什么:阿里篇
    书单来了!大厂的技术牛人在读什么:华为篇
    书单来了!大厂的技术牛人在读什么:腾讯篇
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5732319.html
Copyright © 2011-2022 走看看