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

這是一道LCS方案數的題目,f[j]+=f[j-1](當a[i]==b[j]時)

注意要用高精度!!!

#include<stdio.h>
#include<string.h> 
char a[2001];
char b[2001],la,lb;
int mod=1e8;	
int f[2001][2001];
int cnt[2001];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	scanf("%s%s",a+1,b+1);
 	f[0][1]=1; 
 	cnt[0]=1;
    for(int i=0;i<=m;i++) 
		cnt[i]=1;
	for(int i=1;i<=n;i++)
	{
		if(a[i]=='A')
			a[i]='T';
		else if(a[i]=='C')
			a[i]='G';
		else if(a[i]=='T')
			a[i]='A';
		else
			a[i]='C';				
	}
	for(int i=1;i<=n;i++)
		for(int j=m;j>0;j--)
		{
			if(a[i]!=b[j])
				continue;
			if(cnt[j]<cnt[j-1])
				cnt[j]=cnt[j-1];
        	for(int l=1;l<=cnt[j];l++) 
			{
        		f[j][l]+=f[j-1][l];
        		if(f[j][l]>=mod) 
        		{
					f[j][l+1]+=f[j][l]/mod;
					f[j][l]%=mod;		        	
		        }
        	}
	        while(f[j][cnt[j]+1]) 
				cnt[j]++;			
		}
	printf("%d",f[m][cnt[m]]);
    for(int i=cnt[m]-1;i>0;i--) 
		printf("%08d",f[m][i]);				
}
f數組的第二維我用一個cnt來存的,爲了求高精度.

剩下的就不難了.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章