bzoj4606 DNA

题意有点复杂,就自己去看吧。

题解

f[i][j][k]表示第i为,为-j范式,当前位为k的方案数,从后往前dp一遍。

然后再贪心的从前往后填数。但注意当前填的数已经是-cur范式,计算方案的时候要用k-cur来算。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define maxn 100020
 7
 8 typedef long long ll;
 9 ll f[maxn][11][4],R;
10 int mp[200],a[maxn],ans[maxn];
11 int n,k;
12 char ch[maxn],re[5];
13
14 void init(){
15     if ( a[n] == 5 ){
16         for (int l = 0 ; l <= 3 ; l++){
17             for (int i = 1 ; i <= k ; i++){
18                 f[n][i][l] = 1;
19             }
20         }
21     }
22     else{
23         for (int i = 1 ; i <= k ; i++)f[n][i][a[n]] = 1;
24     }
25     for (int i = n - 1 ; i ; i--){
26         if ( a[i] < 5 ){
27             for (int j = 1 ; j <= k ; j++){
28                 for (int l = 0 ; l <= 3 ; l++){
29                     if ( a[i] >= l ) f[i][j][a[i]] += f[i + 1][j][l]; //如果有这种转移就不能在用f[i + 1][j - 1][l]在更新了。因为f[i + 1][j][l]已经包含了它的方案数,否则会算重
30                     else f[i][j][a[i]] += f[i + 1][j - 1][l];
31                 }
32             }
33         }
34         else{
35             for (int l = 0 ; l <= 3 ; l++){
36                 for (int j = 1 ; j <= k ; j++){
37                     for (int p = 0 ; p <= 3 ; p++){
38                         if ( l >= p ) f[i][j][l] += f[i + 1][j][p];
39                         else f[i][j][l] += f[i + 1][j - 1][p];
40                     }
41                 }
42             }
43         }
44     }
45 /*    for (int i = 1 ; i <= n ; i++)
46        for (int l = 0 ; l <= 3 ; l++)
47         for (int j = 1 ; j <= k ; j++){
48             f[i][j][l] += f[i][j - 1][l];
49         }*/
50 }
51 void solve(){
52     int cur = 1;
53     ans[0] = 5;
54     for (int i = 1 ; i <= n ; i++){
55         if ( a[i] == 5 ){
56             ll sum[4];
57             for (int l = 0 ; l <= 3 ; l++){
58                 if ( ans[i - 1] < l ) sum[l] = f[i][k - cur][l];
59                 else sum[l] = f[i][k - cur + 1][l];
60             }
61             for (int l = 3 ; l >= 0 && R > 0 ; l--){
62                 ans[i] = l , R -= sum[l];
63             }
64             R += sum[ans[i]];
65             if ( ans[i - 1] < ans[i] ) cur++;
66         }
67         else{
68             ans[i] = a[i];
69             if ( ans[i - 1] < ans[i] ) cur++;
70         }
71     }
72     for (int i = 1 ; i <= n ; i++) printf("%c",re[ans[i]]);
73     printf("\n");
74 }
75 int main(){
76     freopen("input.txt","r",stdin);
77     mp[‘A‘] = 3 , mp[‘C‘] = 2 , mp[‘G‘] = 1 , mp[‘T‘] = 0 , mp[‘N‘] = 5;
78     re[3] = ‘A‘ , re[2] = ‘C‘ , re[1] = ‘G‘ , re[0] = ‘T‘;
79     scanf("%d %d %lld",&n,&k,&R);
80     scanf("%s",ch + 1);
81     for (int i = 1 ; i <= n ; i++) a[i] = mp[(int)ch[i]];
82     init();
83     solve();
84 }
时间: 2024-10-05 23:46:27

bzoj4606 DNA的相关文章

【BZOJ4606】[Apio2008]DNA DP

[BZOJ4606][Apio2008]DNA Description 分析如DNA序列这样的生命科学数据是计算机的一个有趣应用.从生物学的角度上说,DNA 是一种由腺嘌呤.胞嘧啶.鸟嘌呤和胸腺嘧啶这四种核苷酸组成的链式结构.这四种核苷酸分别用大写字母A.C.G.T表示.这样,一条DNA单链可以被表示为一个只含以上四种字符的字符串.我们将这样的字符串称作一个DNA序列 .有时生物学家可能无法确定一条DNA单链中的某些核苷酸.在这种情况下,字符N将被用来表示一个不确定的核苷酸.换句话说,N可以用来

UVA - 1368 DNA Consensus String

DNA Consensus String Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description  Figure 1. DNA (Deoxyribonucleic Acid) is the molecule which contains the genetic instructions. It consists of four different nuc

[LeetCode]Repeated DNA Sequences

题目:Repeated DNA Sequences 给定包含A.C.G.T四个字符的字符串找出其中十个字符的重复子串. 思路: 首先,string中只有ACGT四个字符,因此可以将string看成是1,3,7,20这三个数字的组合串: 并且可以发现{ACGT}%5={1,3,2,0};于是可以用两个位就能表示上面的四个字符: 同时,一个子序列有10个字符,一共需要20bit,即int型数据类型就能表示一个子序列: 这样可以使用计数排序的思想来统计重复子序列: 这个思路时间复杂度只有O(n),但是

POJ2778 DNA Sequence Trie+矩阵乘法

题意:给定N个有A C G T组成的字符串,求长度为L的仅由A C G T组成的字符串中有多少个是不含给定的N个字符串的题解: 首先我们把所有的模式串(给定的DNA序列)建Trie,假定我们有一个匹配串,并且在匹配过程到S[i]这个字符时匹配到了Trie上的某个节点t,那么有两种可能: 匹配失败:t->child[S[i]]为空,跳转到t->fail,因此t->fail一定不能是某个模式串的结尾: 匹配成功:跳转到t->child[S[i+1]],因此t->child[S[i

CodeForces 520C DNA Alignment

题意: 一段DNA序列(10^5长度)  定义h函数为两序列相同碱基个数  p函数为分别移动两个DNA序列后所有可能的h函数之和  问使p最大的序列有多少个 思路: 根据p函数的定义  我们发现p这个函数其实就是A序列每个碱基和B序列每个碱基比较再乘一个n 因此可以贪心构造B序列  即每次新加一个碱基必定是A序列中出现次数最多的碱基 那么最后的答案就是A序列中出现次数最多的碱基种类数的n次方 代码: #include<cstdio> #include<iostream> #incl

HDU - 1560 DNA sequence

给你最多8个长度不超过5的DNA系列,求一个包含所有系列的最短系列. 迭代加深的经典题.(虽然自己第一次写) 定一个长度搜下去,搜不出答案就加深大搜的限制,然后中间加一些玄学的减枝 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<

DNA Pairing

DNA 链缺少配对的碱基.依据每一个碱基,为其找到配对的碱基,然后将结果作为第二个数组返回. Base pairs(碱基对) 是一对 AT 和 CG,为给定的字母匹配缺失的碱基. 在每一个数组中将给定的字母作为第一个碱基返回. 例如,对于输入的 GCG,相应地返回 [["G", "C"], ["C","G"],["G", "C"]] 字母和与之配对的字母在一个数组内,然后所有数组再被组织

如何使用3D MAX建造出DNA双螺旋结构

首先,在基本上掌握了DNA双螺旋结构以及3DMAX的简单的使用方法之后,我们便可以建造DNA双螺旋结构了. 在 3DMAX中利用基本标准形状来建造单个碱基配对的情况,即利用基本形状中的球体和圆柱体来构造两颗求和圆柱连接在一起,调整好自己想要的形状即可.之后,先调整一下轴,也就是选中索要调整轴心的对象,然后点击层次那个按钮,之后点击仅影响轴,在对象上可以移动到自己想要的轴心的位置.(提示,如果想要精确的移动轴心的话,可以打开捕捉,然后点击右键,点击轴心,就可以轻松地捕捉轴心的位置了).然后选中所要

HBV DNA level _data analysis

HBV 表明抗原阳性是HCC最重要风险因子 Seropositivity for the hepatitis B surface antigen (HBsAg) is one of the most important risk factors for hepatocellular carcinoma hbv e 抗原阳性会增加HCC风险 In our previous study, seropositivity for the hepatitis B e antigen (HBeAg) was