【URAL 1513】Lemon Tale(DP+高精度)

【URAL 1513】Lemon Tale(DP+高精度)

题目大意:找出’L’和’B’组成的长N的串,满足连续的’L’的个数不超过M个的方案数。

考虑 dp[i][j](1in,0jm) 表示遍历到第i个位置时,连续有j个’L’的方案数。
转移为 dp[i][0]=0jmdp[i1][j],dp[i][j]=dp[i1][j1](0<jm) 暴力的话是 108 不知道给不给过。

想了个优化,令 sum[i]=0jmdp[i][j] ,那么 dp[i][0]=sum[i1] ,最后答案就是 sum[n]

现在考虑对sum的维护,每次转移时 sum[i]=sum[i1]dp[i1][m]+dp[i][0]

其实就是 sum[i]=2sum[i1]dp[i1][m] ,这样其实只要维护 dp[i][m] 就行了——双向队列,对首为 dp[i][m] ,因为 dp[i][m]=dp[i1][m1] ,所以每次取出对首 dp[i1][m] ,新的对首又变成 dp[i][m]

PS:此题要高精度……BigNum就不贴了

代码如下:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define Pr pair
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)

using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-8;
const int maxn = 11234;

deque  q;

int main()
{
    //fread("");
    //fwrite("");

    int n,m;
    BigNum now,ze;
    now = 1;
    ze = 1;

    scanf("%d%d",&n,&m);

    for(int i = 0; i < m; ++i) q.push_back(0);
    q.push_back(ze);

    for(int i = 0; i < n; ++i)
    {
        ze = now;
        now = now*2-q.front();
        q.pop_front();
        q.push_back(ze);
    }

    now.print();

    return 0;
}

你可能感兴趣的:(DP,ACM之DP)