码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2764 [JLOI2011]基因补全

时间:2015-02-26 21:43:42      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:dp   高精度   

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2764

题意:给定一个长度为n的碱基序列S和一个长度为m的碱基序列T,现在希望向序列T里补一定的碱基使得序列S和序列T配对,配对的规则是AT配对,CG配对,添加碱基的位置与数量不同的方案视为不同,求不同的方案数。0<mn2000

题解:
可以考虑算出序列T在序列S里匹配的本质不同方案数,利用dp可以很容易解决这个问题。
f[i][j]表示序列S前i位匹配序列T至第j位的方案数,则对于f[i][j],若不用S[i]匹配T[j],则为f[i?1][j],若能匹配,则可由f[i?1][j?1]转化至该状态,最终的答案为f[n][m],dp可滚动。
粗略估计答案的上界,可以发现存在情况使得答案超过264,但不可能超过C(2000,1000)或者更小,dp直接配上高精度即可。

代码:

#include <cstdio>
const int maxn = 2001, maxl = 70, mod = 1000000000;
struct BigInt
{
    int len, num[maxl];
    void getint(const int &x) { num[len++] = x; }
    void Print()
    {
        printf("%d", num[len - 1]);
        for(int i = len - 2; i >= 0; --i)
            printf("%9.9d", num[i]);
        putchar(‘\n‘);
    }
    void operator += (const BigInt &x)
    {
        if(len < x.len) len = x.len;
        for(int i = 0; i < len; ++i)
        {
            num[i] += x.num[i];
            if(num[i] >= mod)
            {
                num[i] -= mod;
                ++num[i + 1];
            }
        }
        if(num[len]) ++len;
    }
} f[maxn];
inline bool check(char a, char b)
{
    return a == ‘A‘ && b == ‘T‘ || a == ‘G‘ && b == ‘C‘ || a == ‘C‘ && b == ‘G‘ || a == ‘T‘ && b == ‘A‘;
}
int n, m;
char s[maxn], t[maxn];
int main()
{
    scanf("%d%d%s%s", &n, &m, s, t);
    f[0].getint(1);
    for(int i = 1; i <= n; ++i)
        for(int j = m; j; --j)
            if(check(s[i - 1], t[j - 1])) f[j] += f[j - 1];
    f[m].Print();
    return 0;
}

BZOJ 2764 [JLOI2011]基因补全

标签:dp   高精度   

原文地址:http://blog.csdn.net/skywalkert/article/details/43955953

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!