【bzoj2764】[JLOI2011]基因补全 dp+高精度
题目描述
在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对。两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的。例如ACGTC能且仅能与TGCAG配对。一个相对短的碱基序列能通过往该序列中任意位置补足碱基来与一个相对长的碱基序列配对。补全碱基的位置、数量不同,都将视为不同的补全方案。现在有两串碱基序列S和T,分别有n和m个碱基(n>=m),问一共有多少种补全方案。
输入
数据包括三行。
第一行有两个整数n,m,表示碱基序列的长度。
第二行包含n个字符,表示碱基序列S。
第三行包含m个字符,表示碱基序列T。
两个碱基序列的字符种类只有A,C,G,T这4个大写字母。
输出
答案只包含一行,表示补全方案的个数。
样例输入
10 3
CTAGTAGAAG
TCC
样例输出
4
题解
高中生物 dp+高精度
根据碱基互补配对原则,S的互补链是确定的,所以所求转化为在S的互补链中依次选择m个不同种碱基。。。
设f[i]为将T串的前i个选完的方案数。
那么对于S中的位置i和T中的位置j,如果它们互补,则更新答案,f[j]+=f[j-1]。
注意需要倒着循环,因为S串中的每个碱基只能用一次。
注意需要高精度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <cstdio> #define mod 100000000 char s1[2010] , s2[2010]; struct data { int len , num[100]; data operator+=( const data a) { int i; for (i = 0 ; i < len || i < a.len || num[i] ; i ++ ) num[i] += a.num[i] , num[i + 1] += num[i] / mod , num[i] %= mod; len = i; return * this ; } void output() { int i; printf ( "%d" , num[len - 1]); for (i = len - 2 ; i >= 0 ; i -- ) printf ( "%08d" , num[i]); printf ( "\n" ); } }f[2010]; bool judge( char a , char b) { return (a == 'A' && b == 'T' ) || (a == 'G' && b == 'C' ) || (a == 'C' && b == 'G' ) || (a == 'T' && b == 'A' ); } int main() { int n , m , i , j; scanf ( "%d%d%s%s" , &n , &m , s1 + 1 , s2 + 1); f[0].len = f[0].num[0] = 1; for (i = 1 ; i <= n ; i ++ ) for (j = m ; j ; j -- ) if (judge(s1[i] , s2[j])) f[j] += f[j - 1]; f[m].output(); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!