zoukankan      html  css  js  c++  java
  • dp+树状数组

    给定一个长度为 N 的序列 A,求 A有多少个长度为 M 的严格递增子序列。

    输入格式

    第一行包含整数 TT,表示共有 T 组测试数据。

    每组数据,第一行包含两个整数 N 和 M。

    第二行包含 N 个整数,表示完整的序列 A。

    输出格式

    每组数据输出一个结果,每个结果占一行。

    输出格式为 Case #x: yx 为数据组别序号,从 11 开始,yy 为结果。

    由于答案可能很大,请你输出对 1e9+7取模后的结果。

    数据范围

    1T100
    1MN1000
    Ti=1Ni×Mi1e7
    序列中的整数的绝对值不超过1e9

    输入样例:

    2
    3 2
    1 2 3
    3 2
    3 2 1
    

    输出样例:

    Case #1: 3
    Case #2: 0



    f[maxn][maxn];//以第i个结尾时,有j个递增的方案数
    优化之前的代码时这样的:
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e3+100;
    const int mod=1e9+7;
    int a[maxn],t;
    int f[maxn][maxn];//以第i个结尾时,有j个递增的方案书 
    int n,m;
    int main(){
        cin>>t;
        int kase=0;
        while(t--){
            memset(f,0,sizeof(f));
            cin>>n>>m;
            for(int i=1;i<=n;i++){
                cin>>a[i];
            }
            f[1][1]=1;
            for(int i=1;i<=n;i++){
                f[i][1]=1;
            }
            for(int i=2;i<=n;i++){
                for(int j=1;j<m;j++){
                    for(int k=1;k<i;k++){ 
                        if(a[i]>a[k]){
                            f[i][j+1]+=f[k][j];    
                        }
                        f[i][j+1]%=mod;
                    } 
                }
            }
            int ans=0;
            for(int i=1;i<=n;i++){
                //cout<<f[i][m]<<endl;
                ans+=f[i][m];
                ans%=mod; 
            }
            printf("Case #%d: %d
    ",++kase,ans);
        } 
        
    }
    然后可以用线段树或者树状数组优化掉一维
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    typedef long long ll;
    using namespace std;
    const int maxn=1e3+100;
    const int mod=1e9+7;
    int a[maxn],t;
    int f[maxn][maxn];//以第i个结尾时,有j个递增的方案数 
    int n,m;
    int cnt=0; 
    int c[maxn]; 
    int num[maxn];
    int lowbit(int x){
        return x&-x;
    }
    void add(int x,int k){
        for(int i=x;i<=cnt;i+=lowbit(i)){
            c[i]=(c[i]+k)%mod;
        }
    }
    int getsum(int x){
        int ans=0;
        for(int i=x;i>0;i-=lowbit(i)){
            ans=(ans+c[i])%mod; 
        }
        return ans;
    }
    int main(){
        cin>>t;
        int kase=0;
        while(t--){
            memset(f,0,sizeof(f));
            cin>>n>>m;
            cnt=0;
            for(int i=1;i<=n;i++){
                cin>>a[i];
                num[++cnt]=a[i];
            }
            sort(num+1,num+cnt+1);
            cnt=unique(num+1,num+cnt+1)-(num+1); 
            for(int i=1;i<=n;i++){
                a[i]=lower_bound(num+1,num+cnt+1,a[i])-num;
            }
            for(int i=1;i<=n;i++){
                f[i][1]=1;
            }
            for(int j=2;j<=m;j++){
                for(int i=1;i<=cnt;i++){
                    c[i]=0;
                } 
                for(int i=1;i<=n;i++){
                    f[i][j]=getsum(a[i]-1);
                    add(a[i],f[i][j-1]);
                }
            }
            int ans=0;
            for(int i=1;i<=n;i++){
                ans+=f[i][m];
                ans%=mod; 
            }
            printf("Case #%d: %d
    ", ++kase,ans);
        }
    } 
     


  • 相关阅读:
    【转载】狐狸的故事
    【android】 资源路径
    【随笔】居然又玩了两天
    【android】 新浪oauth,进度条,AnimationDrawable,Toast,android预定义style
    【随笔】写下现在所想的,开始写博客
    【转】让我们如此享受的慢性毒药
    如何生成SPFILE文件
    如何区别存储过程中的EXIT与RUTURN
    如何设置虚拟机网络
    如何写SQLPLUS例子
  • 原文地址:https://www.cnblogs.com/lipu123/p/14533710.html
Copyright © 2011-2022 走看看