HDU-5568 sequence2(DP+高精度)

sequence2

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


Problem Description
Given an integer array  bi  with a length of  n , please tell me how many exactly different increasing subsequences.

P.S. A subsequence  bai(1ik)  is an increasing subsequence of sequence  bi(1in)    if and only if  1a1<a2<...<akn  and  ba1<ba2<...<bak .
Two sequences  ai  and  bi  is exactly different if and only if there exist at least one  i  and  aibi .
 

Input
Several test cases(about  5 )

For each cases, first come 2 integers,  n,k(1n100,1kn)

Then follows  n  integers  ai(0ai109)
 

Output
For each cases, please output an integer in a line as the answer.
 

Sample Input
   
   
   
   
3 2 1 2 2 3 2 1 2 3
 

Sample Output
   
   
   
   
2 3


好不容易终于又有希望做3题了,结果坑在大数上,还是题没做够,意识没到位


看到上升子序列就往DP想,但是本题不是求最大上升子序列,而是求序列长度为k的不同方案数

一维表示不了,再添一维,则dp[i][j]表示以第i个数为终止数的一个长度为j的序列的不同方案数

状态转移方程:dp[i][j]=dp[i][j]+sum{dp[k][j-1]},(k=1,2,3...i-1);


#include <cstdio>
#include <cstring>
#include <algorithm>

#define LEN 110
#define MOD 100000000

using namespace std;

struct BigInt {//随便找了个高精度模版,不会手写...
    int len,p[LEN];
    BigInt() {
        memset(p,0,sizeof(p));
        len=0;
    }
}dp[105][105],ans;//dp[i][j]表示以第i个数为终止数的一个长度为j的序列的不同方案数

int a[105],s,num,n,k,t;

BigInt add(const BigInt& x,const BigInt& y) {
    BigInt cnt;
    t=max(x.len,y.len);
    for(int i=1;i<=t;i++) {
        cnt.p[i]+=x.p[i]+y.p[i];
        cnt.p[i+1]=cnt.p[i]/MOD;
        cnt.p[i]%=MOD;
    }
    if(cnt.p[t+1])
        t++;
    cnt.len=t;
    return cnt;
}

void print(const BigInt& x) {
    printf("%d",x.p[x.len]);
    for(int i=x.len-1;i>=1;i--)
        printf("%08d",x.p[i]);
    printf("\n");
}

int main() {
    int i,j,x;
    while(scanf("%d%d",&n,&k)==2) {
        memset(dp,0,sizeof(dp));
        memset(ans.p,0,sizeof(ans.p));
        ans.len=0;
        for(i=0;i<n;++i) {
            scanf("%d",a+i);
            dp[i][1].p[1]=dp[i][1].len=1;
        }
        for(i=1;i<n;++i)
            for(j=0;j<i;++j)
                if(a[i]>a[j])//只有当前a[i]>a[j]时才进行状态转移
                    for(x=1;x<n;++x)
                        dp[i][x+1]=add(dp[i][x+1],dp[j][x]);
        for(i=0;i<n;++i)
            ans=add(ans,dp[i][k]);
        print(ans);
    }
    return 0;
}



你可能感兴趣的:(dp,高精度)