BZOJ2764 [JLOI2011]基因补全

Description

在 生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对。两个碱基序列能相互 匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的。例如ACGTC能且仅能与TGCAG配对。一个相对短的碱基序列能通过往该序列中任意 位置补足碱基来与一个相对长的碱基序列配对。补全碱基的位置、数量不同,都将视为不同的补全方案。现在有两串碱基序列S和T,分别有n和m个碱基 (n>=m),问一共有多少种补全方案。

Input

数据包括三行。

第一行有两个整数n,m,表示碱基序列的长度。

第二行包含n个字符,表示碱基序列S。

第三行包含m个字符,表示碱基序列T。

两个碱基序列的字符种类只有A,C,G,T这4个大写字母。

Output

答案只包含一行,表示补全方案的个数。

Sample Input

10 3
CTAGTAGAAG
TCC

Sample Output

4

HINT

样例解释:

TCC的4种补全方案(括号中字符为补全的碱基)

(GA)TC(AT)C(TTC)

(GA)TC(ATCTT)C

(GA)T(CAT)C(TT)C

(GATCA)TC(TT)C

数据范围:

30%数据n<=1000,m<=2

50%数据n<=1000,m<=4

100%数据n<=2000,m<=n

正解:DP+高精度

解题报告:

  好久没写题了,感觉只要不是考试就写不动题了。。。

  这道题其实挺水的,就是一个编辑距离。考虑f[i][j]表示长串匹配到i,短串匹配到j的方案数,显然对于长串而言,我们需要在短串的对应位置补一些新的数字才行。所以f[i][j]=f[i-1][j]表示i这一位上与之相对应的短串上填一个新的数字,并且如果a[i]与b[j]能匹配,那么f[i][j]+=f[i-1][j-1];表示各匹配一位。

  因为答案很大,所以要写高精度。还要滚动数组。

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 2011;
21 const int MOD = 100000000;
22 int n,m;
23 int match[5],a[MAXN],b[MAXN];
24 //int f[MAXN][MAXN][10];//f[i][j]表示长串匹配到i,短串匹配到j的方案数,滚动数组
25 //int cnt[MAXN][MAXN];
26 int cnt[MAXN];
27 int f[MAXN][50];
28
29 inline int getint()
30 {
31        int w=0,q=0;
32        char c=getchar();
33        while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar();
34        if (c==‘-‘)  q=1, c=getchar();
35        while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar();
36        return q ? -w : w;
37 }
38 /*
39 inline void add(int x,int y,int i,int j){
40     int now=1;
41     if(cnt[x][y]<cnt[i][j]) cnt[x][y]=cnt[i][j];
42     while(now<=cnt[x][y]) {
43     f[x][y][now]+=f[i][j][now]; now++;
44     }
45     for(int i=1;i<=cnt[x][y];i++)
46     if(f[x][y][i]>=MOD)
47         f[x][y][i+1]+=f[x][y][i]/MOD,f[x][y][i]%=MOD;
48     while(f[x][y][cnt[x][y]+1]) cnt[x][y]++;
49 }*/
50
51 inline void work(){
52     n=getint(); m=getint(); char c;
53     match[1]=3; match[2]=4; match[3]=1; match[4]=2;
54     for(int i=1;i<=n;i++) {
55     c=getchar();
56     while(c<‘A‘ || c>‘T‘)  c=getchar();
57     if(c==‘A‘) a[i]=1; else if(c==‘C‘) a[i]=2; else if(c==‘T‘) a[i]=3; else a[i]=4;
58     }
59     for(int i=1;i<=m;i++) {
60     c=getchar();
61     while(c<‘A‘ || c>‘T‘) c=getchar();
62     if(c==‘A‘) b[i]=1; else if(c==‘C‘) b[i]=2; else if(c==‘T‘) b[i]=3; else b[i]=4;
63     }
64
65     f[0][1]=1; cnt[0]=1;
66     for(int i=0;i<=m;i++) cnt[i]=1;
67     for(int i=1;i<=n;i++)
68     for(int j=m;j>=1;j--) {
69         if(match[a[i]]!=b[j]) continue;
70         if(cnt[j]<cnt[j-1]) cnt[j]=cnt[j-1];
71         for(int l=1;l<=cnt[j];l++) {
72         f[j][l]+=f[j-1][l];
73         if(f[j][l]>=MOD) f[j][l+1]+=f[j][l]/MOD,f[j][l]%=MOD;
74         }
75         while(f[j][cnt[j]+1]) cnt[j]++;
76     }
77     printf("%d",f[m][cnt[m]]);
78     for(int i=cnt[m]-1;i>=1;i--) printf("%08d",f[m][i]);
79     /*
80     for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) cnt[i][j]=1;
81     for(int i=0;i<=n;i++) f[i][0][1]=1;
82     for(int i=1;i<=n;i++)
83     for(int j=m;j>=1;j--) {
84         if(cnt[i][j]<cnt[i-1][j])cnt[i][j]=cnt[i-1][j];
85         for(int l=1;l<=cnt[i-1][j];l++) f[i][j][l]=f[i-1][j][l]; //一位新添加一个数
86         if(match[a[i]]==b[j]){
87         add(i,j,i-1,j-1);//由上一位转移过来
88         }
89     }
90     printf("%d",f[n][m][cnt[n][m]]);
91     for(int i=cnt[n][m]-1;i>=1;i--) printf("%08d",f[n][m][i]);*/
92 }
93
94 int main()
95 {
96   work();
97   return 0;
98 }
时间: 2024-10-11 22:36:53

BZOJ2764 [JLOI2011]基因补全的相关文章

2764: [JLOI2011]基因补全

2764: [JLOI2011]基因补全 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 570  Solved: 187[Submit][Status][Discuss] Description 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对.两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的.例如ACGTC能且仅能与TGCAG配对.一个

[JLOI2011]基因补全

1973: [JLOI2011]基因补全 Time Limit: 1 Sec  Memory Limit: 256 MB Description 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对.两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的.例如ACGTC能且仅能与TGCAG配对.一个相对短的碱基序列能通过往该序列中任意位置补足碱基来与一个相对长的碱基序列配对.补全碱基的位置.数量不

【bzoj2764】[JLOI2011]基因补全 dp+高精度

题目描述 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对.两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的.例如ACGTC能且仅能与TGCAG配对.一个相对短的碱基序列能通过往该序列中任意位置补足碱基来与一个相对长的碱基序列配对.补全碱基的位置.数量不同,都将视为不同的补全方案.现在有两串碱基序列S和T,分别有n和m个碱基(n>=m),问一共有多少种补全方案. 输入 数据包括三行. 第

BZOJ 2764 [JLOI2011]基因补全

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2764 题意:给定一个长度为n的碱基序列S和一个长度为m的碱基序列T,现在希望向序列T里补一定的碱基使得序列S和序列T配对,配对的规则是A与T配对,C与G配对,添加碱基的位置与数量不同的方案视为不同,求不同的方案数.0<m≤n≤2000. 题解: 可以考虑算出序列T在序列S里匹配的本质不同方案数,利用dp可以很容易解决这个问题. 令f[i][j]表示序列S前i位匹配序列T至第j位的方案数,则对

bzoj2764 基因补全

Description 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对.两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的.例如ACGTC能且仅能与TGCAG配对.一个相对短的碱基序列能通过往该序列中任意位置补足碱基来与一个相对长的碱基序列配对.补全碱基的位置.数量不同,都将视为不同的补全方案.现在有两串碱基序列S和T,分别有n和m个碱基(n>=m),问一共有多少种补全方案. Input

python tab补全

让python的交互解释器支持tab补全.提示功能 方法1: 一.执行python脚本 1.创建一个python脚本,以.py结尾: 脚本如下: import sys import readline import rlcompleter import atexit import os readline.parse_and_bind('tab:complete') histfile =os.path.join(os.environ['HOME'], '.pythonhistory') try: r

linux下的python如何使用tab键补全

一.vim下的补全: pydiction插件 实现功能: 简单python关键词补全 python 函数补全带括号 python 模块补全 python 模块内函数,变量补全 安装步骤: cd ~ wget https://github.com/rkulla/pydiction/archive/master.zip unzip master.zip mkdir -pv ~/.vim/tools/pydiction cp -r pydiction-master/after ~/.vim cp py

VIM的自动补全

自动补全可以很好的提高输入的效率: 触发自动补全的方法总结: 可供弹出式菜单的使用的命令: 其它再补充:

Linux Vim中自动补全Python插件:Pydiction

Pydiction 可以是我们使用Tab键自动补全Python代码在Vim,是一款非常不错的插件. Pydiction不需要安装,所有没有任何依赖包问题,Pydiction主要包含三个文件. python_pydiction.vim  -- Vim plugin that autocompletes Python code. complete-dict         -- Dictionary file of Python keywords, modules, etc. pydiction.p