HDU 5568 sequence2(大数+DP)

原创 2015年11月22日 11:21:02

题意:给一个序列,问有多少个长度为k的上升子序列(对i < j有a[i] < a[j])。

思路:看到上升子序列应想到dp。dp[i][j]表示以a[i]结尾长度为j的上升子序列有多少个。那么得到转移方程:dp[i][j] = sum{dp[k][j-1]},其中 1 <= k < i。

注意此题要用大数BigInteger。

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;

typedef long long LL;
#define mem(a, n) memset(a, n, sizeof(a))
#define ALL(v) v.begin(), v.end()
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define pb push_back
#define eps 1e-8
const int inf = 0x3f3f3f3f, N = 1e2 + 5;

int T, cas = 0;
int n, k;
int a[N];

 #define MAXN 9999
 #define MAXSIZE 10
 #define DLEN 4
 const long long MOD = 258280327;
  class BigInteger
 {
 private:
     int a[300];   // Width 
     int len;       // Length
 public:
     BigInteger(){ len = 1; memset(a, 0, sizeof(a)); }   //Init
     BigInteger(const int);       // Int -> BigInt
     BigInteger(const char*);     // String -> BigInt
     BigInteger(const BigInteger &);  // copy
     BigInteger &operator=(const BigInteger &);   // =
 
     friend istream& operator>>(istream&, BigInteger&);   // >>
     friend ostream& operator<<(ostream&, BigInteger&);   // <<
 
     BigInteger operator+(const BigInteger &) const;   // +
     BigInteger operator-(const BigInteger &) const;   // -
     BigInteger operator*(const BigInteger &) const;   // *
     BigInteger operator/(const int   &) const;        // /
 
     BigInteger operator^(const int  &) const;    //BigInt Pow
     long long    operator%(const long long  &) const;    //Mod Int
     bool   operator>(const BigInteger & T)const;   //Compare with BigInt
     bool   operator<(const BigInteger & T)const;
     bool   operator>(const int & t)const;      //Compare with Int
 
     void print();       //输出大数
 };
 BigInteger::BigInteger(const int b)     //Int - > BigInt
 {
     int c, d = b;
     len = 0;
     memset(a, 0, sizeof(a));
     while (d > MAXN)
     {
         c = d - (d / (MAXN + 1)) * (MAXN + 1);
         d = d / (MAXN + 1);
         a[len++] = c;
     }
     a[len++] = d;
 }
 BigInteger::BigInteger(const char*s)     //String -> BigInt
 {
     int t, k, index, l, i;
     memset(a, 0, sizeof(a));
     l = strlen(s);
     len = l / DLEN;
     if (l%DLEN)
         len++;
     index = 0;
     for (i = l - 1; i >= 0; i -= DLEN)
     {
         t = 0;
         k = i - DLEN + 1;
         if (k<0)
             k = 0;
         for (int j = k; j <= i; j++)
             t = t * 10 + s[j] - '0';
         a[index++] = t;
     }
 }
 BigInteger::BigInteger(const BigInteger & T) : len(T.len)  // copy
 {
     int i;
      memset(a, 0, sizeof(a));
     for (i = 0; i < len; i++)
         a[i] = T.a[i];
 }
 BigInteger & BigInteger::operator=(const BigInteger & n)   //=
 {
     int i;
     len = n.len;
     memset(a, 0, sizeof(a));
     for (i = 0; i < len; i++)
         a[i] = n.a[i];
     return *this;
 }
 istream& operator>>(istream & in, BigInteger & b)   //>>
 {
     char ch[MAXSIZE * 4];
     int i = -1;
     in >> ch;
     int l = strlen(ch);
     int count = 0, sum = 0;
     for (i = l - 1; i >= 0;)
     {
         sum = 0;
         int t = 1;
         for (int j = 0; j<4 && i >= 0; j++, i--, t *= 10)
         {
             sum += (ch[i] - '0')*t;
         }
         b.a[count] = sum;
         count++;
     }
     b.len = count++;
     return in;
 }
 ostream& operator<<(ostream& out, BigInteger& b)   // <<
 {
     int i;
     cout << b.a[b.len - 1];
     for (i = b.len - 2; i >= 0; i--)
     {
         cout.width(DLEN);
         cout.fill('0');
         cout << b.a[i];
     }
     return out;
 }

 BigInteger BigInteger::operator+(const BigInteger & T) const   //+
 {
     BigInteger t(*this);
     int i, big;      //位数
     big = T.len > len ? T.len : len;
     for (i = 0; i < big; i++)
     {
         t.a[i] += T.a[i];
         if (t.a[i] > MAXN)
         {
             t.a[i + 1]++;
             t.a[i] -= MAXN + 1;
         }
     }
     if (t.a[big] != 0)
         t.len = big + 1;
     else
         t.len = big;
     return t;
 }
 BigInteger BigInteger::operator-(const BigInteger & T) const   // -
 {
     int i, j, big;
     bool flag;
     BigInteger t1, t2;
     if (*this>T)
     {
         t1 = *this;
         t2 = T;
         flag = 0;
     }
     else
     {
         t1 = T;
         t2 = *this;
         flag = 1;
     }
     big = t1.len;
     for (i = 0; i < big; i++)
     {
         if (t1.a[i] < t2.a[i])
         {
             j = i + 1;
             while (t1.a[j] == 0)
                 j++;
             t1.a[j--]--;
             while (j > i)
                 t1.a[j--] += MAXN;
             t1.a[i] += MAXN + 1 - t2.a[i];
         }
         else
             t1.a[i] -= t2.a[i];
     }
     t1.len = big;
     while (t1.a[t1.len - 1] == 0 && t1.len > 1)
     {
         t1.len--;
         big--;
     }
     if (flag)
         t1.a[big - 1] = 0 - t1.a[big - 1];
     return t1;
 }
 
 BigInteger BigInteger::operator*(const BigInteger & T) const   //Mutiply with BigInteger
 {
     BigInteger ret;
     int i, j, up;
     int temp, temp1;
     for (i = 0; i < len; i++)
     {
         up = 0;
         for (j = 0; j < T.len; j++)
         {
             temp = a[i] * T.a[j] + ret.a[i + j] + up;
             if (temp > MAXN)
             {
                 temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
                 up = temp / (MAXN + 1);
                 ret.a[i + j] = temp1;
             }
             else
             {
                 up = 0;
                 ret.a[i + j] = temp;
             }
         }
         if (up != 0)
             ret.a[i + j] = up;
     }
     ret.len = i + j;
     while (ret.a[ret.len - 1] == 0 && ret.len > 1)
         ret.len--;
     return ret;
 }
 BigInteger BigInteger::operator/(const int & b) const   //Divide Int
 {
     BigInteger ret;
     int i, down = 0;
     for (i = len - 1; i >= 0; i--)
     {
         ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
         down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
     }
     ret.len = len;
     while (ret.a[ret.len - 1] == 0 && ret.len > 1)
         ret.len--;
     return ret;
 }
 long long BigInteger::operator %(const long long & b) const    //Mod Int
 {
     int i;
     long long d = 0;
     for (i = len - 1; i >= 0; i--)
     {
         d = ((d * (MAXN + 1)) % b + (long long)(a[i])) % b;
     }
     return d;
 }
 BigInteger BigInteger::operator^(const int & n) const    //Pow of BigInteger
 {
     BigInteger t, ret(1);
     int i;
     if (n<0)
         exit(-1);
     if (n == 0)
         return 1;
     if (n == 1)
         return *this;
     int m = n;
     while (m>1)
     {
         t = *this;
         for (i = 1; i << 1 <= m; i <<= 1)
         {
             t = t*t;
         }
         m -= i;
         ret = ret*t;
         if (m == 1)
             ret = ret*(*this);
     }
     return ret;
 }
 bool BigInteger::operator>(const BigInteger & T) const   //Compare with BigInteger
 {
     int ln;
     if (len > T.len)
         return true;
     else if (len == T.len)
     {
         ln = len - 1;
         while (a[ln] == T.a[ln] && ln >= 0)
             ln--;
         if (ln >= 0 && a[ln] > T.a[ln])
             return true;
         else
             return false;
     }
     else
         return false;
 }
 bool BigInteger::operator<(const BigInteger & T) const   //Compare with BigInteger
 {
     int ln;
     if (len > T.len)
         return true;
     else if (len == T.len)
     {
         ln = len - 1;
         while (a[ln] == T.a[ln] && ln >= 0)
             ln--;
         if (ln >= 0 && a[ln] < T.a[ln])
             return true;
         else
             return false;
     }
     else
         return false;
 }
 bool BigInteger::operator >(const int & t) const    //Compare with Int
 {
     BigInteger b(t);
     return *this>b;
 }
 
 void BigInteger::print()    //Print BigInteger
 {
     int i;
     cout << a[len - 1];
     for (i = len - 2; i >= 0; i--)
     {
         cout.width(DLEN);
         cout.fill('0');
         cout << a[i];
     }
     cout << endl;
 }
BigInteger dp[N][N];

int main(){
#ifdef LOCAL
    freopen("/Users/apple/input.txt", "r", stdin);
//	freopen("/Users/apple/out.txt", "w", stdout);
#endif
	
    while(sii(n, k) != EOF) {
    	mem(dp, 0);
    	for(int i = 1; i <= n; i ++) si(a[i]), dp[i][1] = 1;
    	for(int i = 1; i <= n; i ++) {
    		for(int j = 2; j <= k; j ++) {
    			dp[i][j] = 0;
    			for(int k = 1; k < i; k ++) {
    				if(a[k] < a[i]) {
    					dp[i][j] = dp[i][j] + dp[k][j-1];
    				}
    			}
    		}
    	}
    	BigInteger ans = 0;
    	for(int i = 1; i <= n; i ++) ans = ans + dp[i][k];
    	cout << ans << endl;
    }
    
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu5568 sequence2(dp+大数)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5568 题目大意: 给一段长度为n的序列,现在在其中取k个,问这k个是递增的取法有多少种。 范围:n...

HDU-5568 sequence2(DP+高精度)

看到上升子序列就往DP想,但是本题不是求最大上升子序列,而是求序列长度为k的不同方案数 一维表示不了,再添一维,则dp[i][j]表示以第i个数为终止数的一个长度为j的序列的不同方案数 状态转移方程:...

[HDU 5568] sequence2 dp+大数

题意:给定长度为 n 的序列 bi​​,求有多少长度为 k 的但是本质不同的上升子序列。本质不同的意思就是两个子序列中至少有一个位置的下标不同。 思路:dp, dp[i][j] 表示已经选了 i 个...

HDU 5568 dp+大数板子

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

HDU-A Fibonacci sequence斐波那契数列-大数求和

问题及代码: /* *Copyright (c)2014,烟台大学计算机与控制工程学院 *All rights reserved. *文件名称:Fibonacci.cpp *作 者:单...
  • MIKASA3
  • MIKASA3
  • 2015年02月03日 15:01
  • 796

hdu 5064 Find Sequence(DP,单调性优化)

Find Sequence Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)...
  • acm_cxq
  • acm_cxq
  • 2016年07月09日 12:00
  • 115

HDU-5400 Arithmetic Sequence(数学 || DP)

法一: 和队友讨论之后,觉得每一个序列,只要其符合(①公差为d1②公差为d2③前面公差为d1,后面公差为d2)三者任意一个就满足题意 然后求出每一个最长的符合题目条件的序列,然后求其连续子序列(元素个...

HDU 6065 RXD, tree and sequence DP 减少转移情况

给一颗有根树,根节点为1,再给定一个排列,长度为n,要求将排列切分成K段,定义每段的价值为该排列所有点及两两点之间lca中最浅节点的深度。要求输出K段区间所有可能的价值和中的最小值。n*K 解法: ...

HDU 6078 Wavel Sequence【DP+优化】

题目链接 题意:在a和b两串数字中找出两串相等的波浪形序列,问有多少种情况。波浪形序列就是序列的第二个比第一个大,第三个比第二个小,以此类推。 非常难理解的DP,比赛的时候只能想出O(n^4)的算法,...

HDU 4908 (杭电 BC #3 1002题)BestCoder Sequence(DP)

题目地址:HDU 4908 这个题是从m开始,分别往前DP和往后DP,如果比m大,就比前面+1,反之-1.这样的话,为0的点就可以与m这个数匹配成一个子串,然后左边和右边的相反数的也可以互相匹配成一...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 5568 sequence2(大数+DP)
举报原因:
原因补充:

(最多只允许输入30个字)