【OpenJudge9270】【Pku2440】【递推】DNA

本文介绍了一种算法,用于计算在给定长度L的情况下,有多少种可能的DNA序列不会被特定的病毒DNA序列(111和101)感染。通过定义六个状态的递推关系,实现了对所有合法序列计数的高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DNA

【描述】

A kind of virus has attacked the X planet, and many lives are infected. After weeks of study, The CHO (Creature Healthy Organization) of X planet finally finds out that this kind of virus has two kind of very simple DNA, and can be  represented by 101 and 111. Unfortunately, the lives on the planet also have DNA formed by 0s and 1s. If a creature's DNA  contains the virus' DNA, it will be affected; otherwise it  will not. Given an integer L, it is clear that there will be 2 ^ L different lives, of which the length of DNA is L. Your job is to find out in the 2 ^ L lives how many won't be affected? 

【输入】

The input contains several test cases. For each test case it contains a positive integer L (1 <= L <= 10 ^ 6). The end of input is indicated by end-of-file.

【输出】

For each test case,  output K mod 2005, here K is the number  of lives that will not be affected.

【样例输入】

4

【样例输出】

9

【Solution】

  根据题意,111、101是不合法的,所以我们

  令f1[i]为长度为i且结尾三个数是000的所有合法01串数量,

  令f2[i]为长度为i且结尾三个数是001的所有合法01串数量,

  令f3[i]为长度为i且结尾三个数是010的所有合法01串数量,

  令f4[i]为长度为i且结尾三个数是011的所有合法01串数量,

  令f5[i]为长度为i且结尾三个数是100的所有合法01串数量,

  令f6[i]为长度为i且结尾三个数是110的所有合法01串数量。

  设目前长度为n。我们发现000的后两位、100的后两位和f1[n]的最后三位的前两位相等,而多出来的一位有两种情况0和1,选择符合f1[n]最后一位的就行,方案数不变,这样就把f1[n]的最后三位凑全了,f1[n]便可以从f1[n-1]和f5[n-1]转移来。所以f1[n]=f1[n-1]+f5[n-1]

  以此类推:

  f2[n]=f1[n-1]+f5[n-1]

  f3[n]·=f2[n-1]

  f4[n]=f2[n-1]

  f5[n]=f3[n-1]+f6[n-1]

  f6[n]=f4[n-1]

  令dp[n]=f1[n]+f2[n]+f3[n]+f4[n]+f5[n]+f6[n]。下面就是激(奇)动(技)人(淫)心(巧)的数学推导了:

  dp[n]=f1[n]+f2[n]+f3[n]+f4[n]+f5[n]+f6[n]

      =f1[n-1]+f5[n-1]+f1[n-1]+f5[n-1]+f2[n-1]+f2[n-1]+f3[n-1]+f6[n-1]+f4[n-1]

      =dp[n-1]+f3[n-2]+f6[n-2]+f1[n-2]+f5[n-2]+f1[n-2]+f5[n-2]

      =dp[n-1]+f2[n-3]+f4[n-3]+f1[n-3]+f5[n-3]+f3[n-3]+f6[n-3]+f1[n-3]+f5[n-3]+f3[n-3]+f6[n-3]

      =dp[n-1]+dp[n-3]+f1[n-3]+f5[n-3]+f3[n-3]+f6[n-3]

      =dp[n-1]+dp[n-3]+f1[n-4]+f5[n-4]+f3[n-4]+f6[n-4]+f2[n-4]+f4[n-4]

      =dp[n-1]+dp[n-3]+dp[n-4]

1 #include <cstdio>
2 int N;
3 int dp[1000010];
4 int main(){
5    scanf("%d",&N); dp[1]=2; dp[2]=4 ;dp[3]=6; dp[4]=9;
6    for(int i=5;i<=N;++i) dp[i]=(dp[i-1]%2005+dp[i-3]%2005+dp[i-4]%2005)%2005;
7    printf("%d",dp[N]);
8    return 0;
9 }

 

转载于:https://www.cnblogs.com/reddest/p/6005047.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值